This report contains code, plots, maps and analyses that explore Yelp’s academic data set on businesses covering over 150,000 Yelp-rated establishments across over 100 variables.

Univariate Plots Section

[1] 156639
[1] 101

The goals of my exploratory analysis of the Yelp (academic) business data set will be as follows.

  1. Establish an understanding of three key variables: review count, price range and stars (ratings)
  2. Understand and visualize how geography, operating status (open or closed), alcohol service and noise levels can end up affecting the three key variables explored in this data set: review count, price range and stars
  3. Perform the analysis as explained in 1) and 2) on particular segments of Yelp establishments (such as operating restaurants in North America)

In the univariate plots section, the emphasis will be on analysing some of the key variables that will be discussed later in the bivariate and multivariate analysis such as price range, stars, and review count along with other variables such as the geographic dispersion of establishments as well as some information on alcohol service and noise levels.

One of the first things that I want to do to start my analysis is to look at stars (ratings) across all establishments.

From the histogram below, it seems that most ratings are centred around 3.5 to 4 stars, which seems quite consistent with my prior knowledge of Yelp reviews. Generally, people tend to give fairly good reviews!

Of course, the histogram includes both open and closed establishments, and we know that generally speaking establishments that have closed may have closed due to poor business, partly because of poor reviews and opinions of the establishment. What if we only accounted for establishments that were closed and no longer operating? Would this distribution change?

As we can see from the histogram showing the distribution of stars across closed establishments, the distribution in the lower ends do not change much. However, we can see that there is a substantial decline in the proportion of closed establishments that were rated 4.5 and 5 stars. This is definitely a plausible explanation as establishments that are rated highly generally do not close without good reason.

This Yelp data set does not seem to have an equal representation of the number of establishments by geography especially when we account for the differences in population. The majority of establishments in this data set are in Arizona, Ontario and Nevada, with smaller numbers of representation in other states such as North Carolina, Ohio and Quebec. However, Arizona has a population of almost 7 million which is half of Ontario’s population of 14 million, yet has twice the number of establishments being represented. Further, there are only 9 North American states covered in the data set, but there are more than 50 states in the United States and more than 10 within Canada.

In any case, the analysis for review count and stars is far from complete, however, we will revisit these two variables in greater detail in later sections.

For now, let us concentrate on looking at my favourite part of Yelp ratings, which are restaurants! In the following sections and analysis, I will concentrate almost exclusively on operating restaurants located within North America.

[1] 26642

When we partition only for North American restaurants that are operating in this Yelp data set, we find that the number is only 26,642. Out of 156,639 establishments, my area of interest only represents approximately 17% of all establishments. When we partition only for North American states which have a total of 147,658 establishments, this percentage goes up only slightly to 18% (the number of establishments outside North America are minimal).

This is obviously because there are many other such establishments such as nail salons, amusement parks, community centres, spas, along with closed restaurants or restaurants outside of North America that are not included in my analysis.

[1] 147658

As we saw earlier, while there were large variances in the number of establishments in the data set by state, in terms of operating restaurants, there seems more of an even spread out across states with less of a heavy emphasis on Nevada and Arizona.

The plot below shows the top 10 or so cities that were selected for my data analysis, and this was due to the fact that they had the most establishments. Not surprisingly, all the cities above are the largest cities in the states that were in the plot earlier. With the exception of the Phoenix metropolitan area, which covers the cities of Phoenix, Mesa, Scottsdale and Tempe, all the other cities are the only cities that are covered in my analysis within that state.

To start our univariate analysis on restaurants, let us look at the price range across all restaurants.

As we can see from the plot below, the vast majority of restaurants are in the 1-2 low to medium price range, while only a very small proportion (around 5-6 percent) are what we would consider to be the more high-end and expensive type of restaurant (in the 3-4 price range). This sort of makes sense because places such as McDonalds and KFC are factored into the restaurant category as well, and by far the vast majority of restaurants are of the fast-food and take-out variety.

In terms of alcohol service levels in restaurants, we find that its about 50/50. Around half of restaurants (51.3%) will actually serve alcohol of some sort with 15% serving only beer and wine while over 35% will have a full bar. Of course, having alcohol in a restaurant is great, but do alcohol service levels differ amongst different categories of restaurants? The factor that differentiates restaurants the most would probably be the price range.

Alcohol is generally not served in the least expensive restaurants, while those in the price category 2 (average) offer alcohol service at around a 75% rate, and those in in the most expensive restaurants almost all serve alcohol. It is a bit surpising, however, that the percentage of those that offer full bar declines slightly in the highest price range of restaurants.

Of course, an introductory exploratory analysis of Yelp-rated restaurants would not be complete without at least knowing some information on the noise levels of the restaurant. Most restaurants, about two-thirds, had average noise levels, while over 20% are quiet. Only a small minority (around 10%) of restaurants are classified as being in the loud or very loud range.

Univariate Analysis

What is the structure of the data set?

There are 156639 data points in the Yelp academic data set, and includes Yelp-rated establishments across a variety of different geographies that are mainly based in North America. There are 101 variables in the data set and only a few of them were analyzed in my univariate analysis. In the univariate analysis, these include the noise level, alcohol service, price range, stars, and review count.

Aside from review_count which is an integer variable, all other variables follow are categorical in nature:

stars <- 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5
price range <- 1, 2, 3, 4
alcohol service <- none, beer_and_wine, full_bar
noise level <- quiet, average, loud, very_loud
attire <- casual, formal, dressy

The binary (yes/no) variables examined are: is open, delivery, takeout, good for dinner, table service

Geographical information such as longitude is expressed between -180 and 180 degrees, while latitude is expressed between -90 and 90 degrees.

Interesting observations:

  1. Average number of reviews per establishment is around 30
  2. Close to half of ratings are in the 3.5 to 4 stars range
  3. Alcohol service is provided in over 50% of restaurants
  4. Almost all restaurants are in the 1-2 price range (inexpensive to average)
  5. Most restaurants have quiet to average noise levels
  6. The sample of establishments provided in the data set are mostly in Arizona, Nevada and Ontario

What is/are the main feature(s) of interest in your dataset?

The main features of interest in this data set are review count, price range and stars.

What other features in the dataset do you think will help support your investigation into your feature(s) of interest?

Alcohol servoce, noise level, geographical features such as longitude and latitude along with state, is_open, as well as numerous restaurant attributes such as table service, delivery, takeout, attire, if its good for lunch, dinner, dessert etc. would be good features that would complement the analysis on stars, price range and review count.

Did you create any new variables from existing variables in the dataset?

A new variable called full_service was created for the purposes of my analysis (later used in the bivariate analysis section), which is a categorical variable that combines table service, delivery and takeout services all being offered or not. Its value is 1 when table service, delivery and takeout services are provided at the restaurant, and 0 if even one of these services is not offered. The rationale behind creating this variable was to see the percentage of restaurants that were able to respond to all sorts of dining options. There were other variables such as catering, but it was not included as it may have been too restrictive.

I also created a new variable called “value” which is defined as Yelp stars divided by price range, which measures the amount of value that you obtain in terms of an experience at an establishment that for each dollar that you spend. A lower price range and a higher Yelp star rating means a higher value, while conversely, a higher price range and lower Yelp star rating equates a lower value.

Of the features you investigated, were there any unusual distributions? Did you perform any operations on the data to tidy, adjust, or change the form of the data? If so, why did you do this?

There were many cases where null values existed for the restaurant variables and so these values were not included in order to get an approximation of what was only considered to be a restaurant. This prevents including supermarkets or medical clinics or even amusement parks that might have some food services available but are not restaurants on its own. Also, the data has also been subsetted to only account for values in certain states that were operating depending on the analysis. Upon examining the univariate plots, I did not examine any unusual distributions.

Bivariate Plots Section

The number of reviews (review_count) is a very important variable in the Yelp data set. In fact, it is the only variable that is not discrete or categorical other than latitude and longitude, and can be analyzed along a variety of different categorical variables.

As it appears, the review count numbers seem undoubtedly biased towards Nevada and Arizona as shown from the plot below. This sort of makes sense as we saw earlier that the number of establishments were also somewhat biased towards Nevada, Arizona and Ontario. What is odd is that even though NV and ON had a similar number of establishments in this dataset, the number of reviews is substantially higher for NV than it is for ON.

One of the things that I now want to look at is the distribution of review_count by establishment, and to compute the means across each of the states shown above.

At first glance, it seems that are certainly a large number of establishments in Nevada that have an extremely high review count, though the mean number of reviews per establishment is actually only around 30 across the entire data set.

Zooming closer into the box plot, we see that median across all states is somewhere between 7 to 12 reviews, which means that a sizable proportion of Yelp-rated establishments have few to no ratings.

Due to the large number of establishments that have a review count in the thousands, this skews the mean upward considerably such that the mean ends up being double to quadruple the median for each state.

When compared across states, it turns out that the average across each state in terms of the review count per establishment is actually quite different with Nevada having a substantially higher review count than other states. This explains why even though the number of Yelp-rated establishments in Ontario and Nevada are roughly equal, the review_count variable was so much higher for Nevada than for Ontario.

Now, moving on from the review count, what about the relationship between price range and stars for restaurants?

And how does this vary with noise levels? Do more expensive places that are quieter have higher ratings?

Earlier in the univiarate analysis section, we found that most restaurants were of average and quiet noise levels. But why might this be the case? The line plot below shows that there certainly is a ratings premium to having a quiet restaurant as restaurants that were quieter had higher average ratings in general. For example, quiet restaurants had above 3.6 average rating, while very loud restaurants had less than 3.0 average rating.

Although increased noise levels are correlated with decreased Yelp stars for a restaurant, the degree of variance explained from the R-squared is only about 3%, meaning that noise levels only explain a very small proportion of the ratings given to a restaurant. There are most certainly other factors that would most likely influence the number of stars given.

But what else might also impact the number of stars that a Yelp-rated restaurant, could price range be one of them?


Call:
lm(formula = stars ~ attributes.NoiseLevel, data = subset(rest_2))

Residuals:
     Min       1Q   Median       3Q      Max 
-2.59665 -0.53016 -0.03016  0.46984  2.03582 

Coefficients:
                                Estimate Std. Error t value Pr(>|t|)    
(Intercept)                     3.530159   0.005323 663.184  < 2e-16 ***
attributes.NoiseLevelloud      -0.280159   0.016210 -17.283  < 2e-16 ***
attributes.NoiseLevelquiet      0.066491   0.011179   5.948 2.75e-09 ***
attributes.NoiseLevelvery_loud -0.565983   0.027855 -20.319  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.7003 on 25127 degrees of freedom
Multiple R-squared:  0.03003,   Adjusted R-squared:  0.02991 
F-statistic: 259.3 on 3 and 25127 DF,  p-value: < 2.2e-16

It turns out that as the price range for a restaurant increases, the Yelp stars given also tend to be higher, ranging from around 3.4 stars at a price range of 1 and around 3.75 at a price range of 4.

However, doing a quick regression shows that the amount of variance explained by this model is very much insufficient for explaining how many stars a restaurant gets. Although the results in the regression below show statistical significance, this is most likely because there is only one independent variable (as was in the previous case with noise levels). In addition, the amount of variance explained by price range is even less than for noise levels.


Call:
lm(formula = stars ~ attributes.RestaurantsPriceRange2, data = subset(rest_2))

Residuals:
     Min       1Q   Median       3Q      Max 
-2.78659 -0.54650  0.07355  0.45350  1.57355 

Coefficients:
                                  Estimate Std. Error t value Pr(>|t|)    
(Intercept)                       3.306409   0.012854  257.22   <2e-16 ***
attributes.RestaurantsPriceRange2 0.120045   0.007269   16.51   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.7072 on 25129 degrees of freedom
Multiple R-squared:  0.01074,   Adjusted R-squared:  0.0107 
F-statistic: 272.7 on 1 and 25129 DF,  p-value: < 2.2e-16

Looking at the price range again, we can also see that the distribution of price ranges across different geographies vary quite a bit. In the province of Quebec, there is a much higher proportion of restaurants in the more expensive 3-4 categories, and with a substantially lower percentage of restaurants in the less expensive price range 1. This is in stark contrast to AZ (Arizona), NC (North Carolina) and SC (SOuth Carolina) where less expensive ($) restaurants are dominant, and more expensive restaurants are almost non-existent.

And of course printing out the average price range by state, we see that Quebec and Ontario have a much higher average price range compared to the other states in the data set.

When we look at a comparison of price ranges across cities, the fact that Montreal and Toronto have the highest price ranges roughly coincides with our findings earlier in which Quebec and Ontario (where Montreal and Toronto are located respectively) had the highest priced restaurants compared to American states.

One notable exception is Scottsdale in Arizona which had much higher prices than its surrounding municipalities of Phoenix, Tempe and Mesa.

It seems that although the price range of restaurants for Scottsdale and Montreal are quite high, this is matched by the fact that the Yelp stars for restaurants in these cities are also relatively higher compared to other cities as well. So perhaps paying a little more for your food might not be a bad idea!

Of course, I decided to see go a little further and see what the “value” was for restaurants across different cities. I define value as being the number of stars divided by the average price range. What this calculates is the the amount of value added that you obtain for what you eat and pay for at a restaurant. For example, a city with restaurants that have a higher average number of stars or a lower price range will deliver more value for your dollar than those that have lower number of stars or a higher price range.

We find that the cities of the Phoenix metropolitan area such as Phoenix, Mesa, and Tempe to be above average in terms of delivering value for the customer, while cities such as Toronto and Montreal in Canada along with Scottsdale do not deliver as much value for the same amount of money being spent.

While we are on the topic of price and restaurants, I want to explore a bit and look at a new variable called attire and see if the percentage of those expensive 3-4 restaurants line up with the percentage of restaurants where more formal attire is needed.

In fact, we see that the percentage of dressy and formal attire does sort of line up with the percentage of expensive (category 3-4) restaurants that we saw in the stacked bar plot earlier. In fact, the percentage of dressy restaurants actually exceeds those in the price category of 4, so it could be the case that there are some of those more expensive restaurants in the 3 price range that may want people to come in with a dressy attire. That being said, the percentage of restaurants requiring formal attire is almost non-existent across any North American state.

Relative to casual attire, dressy and formal attire positively predicted whether or not a restaurants price range was more expensive or not. Perhaps due to the lack of restaurants requiring formal attire, the impact of dressy attire on predicting a restaurants price range was greater than for formal attire. In this case, the regression can be predicted as such that dressy attire is generally 1.6 higher (relative to casual) in terms of price range on average (out of 4), while the price range is only 0.6 higher for formal attire (relative to casual). It is also of interest that 15% of variance in terms of predicing price range is explained by attire on its own.


Call:
lm(formula = attributes.RestaurantsPriceRange2 ~ attributes.RestaurantsAttire, 
    data = subset(restaurant_dress))

Residuals:
    Min      1Q  Median      3Q     Max 
-2.0719 -0.6186  0.3814  0.3814  2.3814 

Coefficients:
                                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)                         1.61860    0.00363 445.944  < 2e-16 ***
attributes.RestaurantsAttiredressy  1.45325    0.02222  65.397  < 2e-16 ***
attributes.RestaurantsAttireformal  0.63140    0.10023   6.299 3.04e-10 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.5666 on 25068 degrees of freedom
Multiple R-squared:  0.1468,    Adjusted R-squared:  0.1467 
F-statistic:  2156 on 2 and 25068 DF,  p-value: < 2.2e-16

Let us look at little bit further into dining options at a restaurant. A good restaurant should always provide a large variety of dining options, and so I have constructed a variable called “Full_service” that has a value of 1 whenever delivery, takeout and table services are all provided, and 0 whenever even one of these services were not provided.

It seems that very few operating restaurants do delivery, take-out and dine-in all at once. The main reason for this lack of full service offerings is predominately due to the lack of delivery service being offered across restaurants (around 20-25% of restaurants do it). However, virtually all restaurants offer take out service with the notable exception of Quebec having a much lower percentage while also simultaneously having more restaurants that are are dine-in with table service.

Most of the analysis so far has been on a state level, and so I would like to delve more into analyzing restaurants or establishments in general on a city level with an emphasis on geographical distribution of restaurants across different variables. Some questions that I really want to explore are:

  1. Where within each city are restaurants located? Are they evenly spread across downtown and suburban areas?
  2. And how does this vary by price range?
  3. And are higher rated restaurants more concentrated in certain parts of the city?
  4. Are noisier restaurants spread out across the city or are they mainly in the downtown core?
  5. Are alcohol service levels in restaurants consistent throughout different parts of the city? And lastly:
  6. Where are some good places for dinner?

In this geographic analysis, I am going to focus on three cities, Toronto, Montreal and Phoenix, and this is because these three cities were among the top 3-4 cities that had the most restaurants represented within Yelp. I also briefly examine Scottsdale (which is to the northeast of Phoenix) because it might be interesting to analyze as the the city seems to have much higher restaurant prices despite its proximity.

In Toronto, restaurants are mainly concentrated in the downtown core, and have a large concentrated presence along the main thoroughfare Yonge Street which extends all the up vertically through the centre of the map.

In Montreal, the restaurants are even more concentrated, particularly in the downtown core and in the Plateau-Mont-Royal area just directly to the northwest of the downtown area. Restaurants outside this area are fairly spread out and are much lower in number, which partly has to do with the fact that Montreal is a much more densely populated city than Toronto.

In Phoenix, restaurants seem to be spread evenly across the city in a grid-like pattern with a slightly larger concentration in the downtown southcentral square area in the middle of the map (with all four highways surrounding it). One can also see on the map that to the east are Scottdale and Tempe, both of which are separate cities represented within the Yelp data set (though not very well represented compared to Phoenix). Nonetheless, I decide to take a further look at least specifically into Scottsdale (one of the larger cities just outside Phoenix) anyway.

The concentration of restaurants in Scottsdale seems to be along one narrow vertical street known as Scottsale Road. The restaurants in Scottsdale are much more concentrated in specific areas than was the case with Phoenix which is just to the west of the city.

Restaurants which are in the average (2) price range are found everywhere throughout Toronto, and corresponds almost precisely with the earlier map showing restaurants across Toronto. However, inexpensive (1) price range restaurants are mainly concentrated in the downtown core and in the north-central part of the city. Other parts of the city (especially just above the downtown area) had far fewer inexpensive restaurants than in the downtown core and the north-central end along Yonge Street.

The restaurants in the more expensive (3) price range were once again concentrated in the downtown core, but were also prevalent going north along Yonge street (the main thoroughfare that runs down the centre of the city). The priciest restaurants (4) were only to be found almost exclusively along Yonge street stretching from the waterfront lake area up to around Hwy 401 in the north-central end of the city.

It seems that the more expensive restaurants in the 3 range are almost as prevalent as those in the 1 price range, while those in the most expensive price category 4 are actually quite visible in the downtown core. The geographic concentration of more expensive restaurants in a particular locale is definitely higher than in Toronto.

Restaurants in the 1 price range are found everywhere in Phoenix as in the original Phoenix map with all restaurants across price ranges shown. Average restaurants in the 2 price range were less numerous and were mainly concentrated in the downtown core and the northern part of the city. On the other hand, other than a smaller cluster in the city centre and a few restaurants spread out in the northeastern part of the city, the more expensive restaurants in the 3 price range were non-existent. The priciest (4) restaurants are found scattered throughout the city and number no more than 20.

At least compared to Toronto and Montreal, there were fewer pricey restaurants relative to the total number. This kind of makes sense, as we saw earlier that by comparing percentage of restaurants by price range, Ontario (where Toronto is located) and Quebec (where Montreal is located) had far more restaurants in the 3-4 price range than in Arizona (Where Phoenix is located).

While the 1-2 price range restaurants dominated (as always), there were actually two clusters of restaurants in the more expensive (3) price range in Scottsdale concentrated in downtown Scottsdale and in Paradise Valley along Scottsdale Road. Since both Tempe and Mesa (to the southeast of Phoenix) had similar price ranges for its restaurants, this suggests that the more expensive restaurants in the Phoenix metropolitan area are found in Scottsdale.

I conclude the bivariate plots section with a quick look at how geographic concentration of restaurants vary by Yelp stars.

Because of the large number of restaurants in the 3 to 4 star range, there is not much to be said here. However, at the extremes, 1 star and 5 star, there seem to be some degree of geographic concentration that differs from the other star ranges. Restaurants rated 1 and 1.5 tend to be more prevalent in the northwestern part of the city, while restaurants rated 5 tend to be located just to the west of the downtown core.

In Phoenix, what we can see immediately is that the restaurants rated between 1 to 1.5 stars are most likely in the western half (suburban) of the city, but for all other Yelp stars, restaurants could be found all over the city.

So far, this geographical analysis of the location of restaurants in these cities has been interesting. More will be discussed using a greater number of variables later on.

Bivariate Analysis

Talk about some of the relationships you observed in this part of the investigation. How did the feature(s) of interest vary with other features in the dataset?

  1. More expensive restaurants in higher price ranges tend to be rated more highly, however the percentage of variance explained by the effect of price on stars is negligible indicating that there are most likely many other factors that explain the average Yelp star rating that a restaurant receives.

  2. The review count of all Yelp-rated establishments is disproportionately represented by Nevada and Arizona, with Nevada having a much higher average number of reviews for its establishments compared with the other 8 states in the data set.

  3. The Canadian provinces of Quebec and Ontario along with its major cities Toronto and Montreal had the highest average price ranges for its restaurants, while Arizona along with its major cities of the Phoenix metropolitan area (Phoenix, Tempe, and Mesa) had the lowest average price ranges.

  4. In terms of ratings, Scottsdale in AZ and Montreal in QC had higher Yelp stars rated for its restaurants than other North American cities.

  5. In terms of getting the most value out of your dollar in a restaurant, the cities of the Phoenix metropolitan area (except Scottsdale) scored the highest relative to the other cities.

  6. Around only 10-25% of restaurants offer a full suite of dining options such as delivery, take-out and table service (dine-in). This was mainly due to the relatively low percentage of restaurants that did delivery.

  7. Restaurants in Toronto and montreal are concentrated mainly in the downtown core, while other cities such as Phoenix had its restaurants spread out across the city.

  8. While more expensive restaurants (price range 3-4) were found in the same places as where its highest concentration was in (usually downtown core), this was not necessarily the case in the Phoenix metropolitan area (Phoenix, Scottsdale etc.), where its most expensive restaurants were in nearby Scottsdale, with the Phoenix downtown core being almost devoid of restaurants in the 3-4 price range. More expensive in the 3-4 price range were quite prevalent in Montreal (almost as many as those in the 1 price range) than compared to other cities.

Did you observe any interesting relationships between the other features (not the main feature(s) of interest)?

  1. Restaurants with lower noise levels (quiet) tend to have higher ratings as well, though for the same reasons as price range, this effect (on its own) is negligible.

  2. Very few restaurants required formal or dressy attire, though Quebec seemed to score just slightly higher relative to other states.

What was the strongest relationship you found?

In terms of my geographic analysis of the 4 cities above, the strongest relationship that I found was that all restaurants regardless of price range were almost always concentrated in the downtown core or in some narrow strip outside of a central area.

Multivariate Plots Section

Moving on from looking at price ranges, let us now explore the geographical distribution of alcohol service across restaurants in Toronto. The map above shows that most full bar services are concentrated downtown, though there is a large area in the very centre of the downtown core in which either no alcohol is provided or only beer and wine is. Most places to the northwest and northeast of the downtown cluster of restaurants in the middle also did not provide alcohol services either.

In Phoenix, it seems that alcohol is offered in fewer restaurants than was the case in Toronto, and it is clear from the map above that most resturants to the south and west of interstate did not offer a full bar. Even within the centre of Phoenix, there exist large areas that do not offer alcohol or only offer beer and wine.

In Montreal, it is much harder to tell where the geographic concentration of alcohol service is within restaurants throughout the city. It seems like a massive concentration of full bar services in the downtown core, with an even mix of alcohol service levels being provided by restaurants in the peripheral areas of the city.

Next up, I wanted to see if noise levels differed between different downtown and suburban areas of Toronto. In our previous analysis of noise levels, we saw that two-thirds of restaurants were average in terms of noise levels, so it is not surprising to see average noise levels (in red) dominate throughout the city. The restaurants in the southeastern and northwestern parts of the city seem be mainly average or quiet. The rest of the city, however, seems to be sprinkled quite evenly with restaurants with all sorts of noise levels.

In the case of Phoenix, restaurants of all noise levels were evenly sprinkled throughout the city. It seems there is little to no correlation between restaurant noise levels and geographic dispersion.

Unlik Phoenix and Toronto, Montreal does have a few areas, particularly in the areas to the northeast and south of the downtown core, that are actually dominated exclusively by average and quiet restaurants. At least among these three cities, in general, restaurants of all noise levels seem to be sprinkled throughout the city.

In the next few plots, as a matter of personal interest, I am going to look at where places that are good for going out for dinner are located within a city.

In Toronto, the best places to find restaurants that are good for dinner are in the downtown core and along Yonge Street (the vertical street through the centre of the city that’s filled with restaurants). However, in terms of the percentage of places that are for dinner, the cluster of restaurants in the northern part of the city along Yonge Street, and the downtown area close to the lake but just across from the island in the southcentral part of the city are the best places to go if one wanted to look exclusively for dinner places when going out at night. On the other hand, the northwestern part of Toronto seems to be fairly devoid of places to go out to for dinner.

Compared to Toronto, it seems that Phoenix has a much wider geographical dispersion of restaurants that are for good for dinner as compared to Toronto, though the north central area of the city seems to have a higher concentration than the southern and western parts of the city.

When it comes to restaurants that are good for dinner as a percentage of total number of restaurants, Toronto and Phoenix seem to be approximately the same in terms of its percentage, even though the geographical concentration of places that are good for dinner vary quite a bit.

Looking back to Montreal again one last time, we see that dinner places are not as prevalent as in Toronto or Phoenix. Only parts of the downtown core and in Westmount to the immediate southwest of the downtown core have high concentrations of places that are good for dinner.

We now step away from geographic analysis entirely and go back to looking at overall relationships between our main variables of interest, price range, review count and stars on a multivariate level.

In earlier analyses, the main focus was always on operating restaurants within North America, and in the beginning of the analysis, there was not much discussion on the operating status variable, is_open, and review count was mainly looked at on a more general and geographic level.

In this scatterplot above, the relationship between the number of reviews and stars given for a restaurant is quite clear. Almost all establishments that have above 1000 reviews continue to be open, while almost all of the establishments that were closed had less than 1000 reviews. We also see above that restaurants with higher review counts tend to be higher on the rating scale as virtually all establishments that had more than 1000 reviews were given a rating of at least 2.5 stars.

The relationship we saw earlier between number of reviews and ratings across closed and open establishments holds true too for operating restaurants in North America.

When we include price range into our earlier scatterplot and have the percentage of reviews as the size of the relationship between price range and ratings, we find virtually all reviews are for restaurants that have between a 3.5-4.5 rating on Yelp, and that this is consistent across all price ranges. However, the percent of total review counts within each price range and stars combination at a Yelp star of 3 or lower declines as the price range gets higher. This is of course consistent with the line plot shown previously where the average stars given tended to go up as the price range increased.

Now, it is time to do some deeper analysis into the distribution of Yelp stars across different geographies and types of establishments.

It seems like across all Yelp establishments (both open and closed, whether a restaurant or not), Arizona and Nevada seem to have a much larger percentage of their establishments being rated at 4 stars or higher, and this is more pronounced at 5 stars.

Our main establishments of interest, however, are for operating restaurants, and not necessarily just any type of establishment, as Yelp-rated establishments could include nail salons, spas, community centres as described earlier at the beginning of this project.

When we only look at operating restaurants, we find that the story changes quite a bit. Instead of having Arizona and Nevada dominate the rankings in the 4.5 to 5 stars range, we see that the distribution of stars across all states is relatively the same and centred around 3.5 to 4 stars. It is interesting to note that Quebec seems to have a far higher percentage of restaurants in higher star ranges than other states such as Arizona or South Carolina.

This can be seen in the average stars by state chart below.

Aside from geography, there are also other variables such as noise levels and alcohol service that I would like to explore in terms of its relation to our main variables of interest, price range and stars.

Earlier, we saw that whenever noise levels were higher, the average number of Yelp stars for a restaurant was lower, resulting in a clear downward relationship between the two variables. However, when we create a multivariate plot to group this relationship by price range, we find that across each price range, a restaurant that is louder will always have a lower average rating (though the effect is minor between average versus quiet noise levels). The only notable exception is at price range 3, where a restaurant with an average noise level does slightly better than those at a quiet noise level.

Also, it is interesting that at the most expensive price range 4, the average stars for a very loud restaurant decreases compared to those at the price range 3, while for a quiet restaurant, the increase in the average number of stars from price range 3 is much greater than in previous price ranges. As a result, the difference in average stars given for a very loud versus a quiet restaurant at the most expensive price range 4 is a difference of almost 1 whole star!

Next, let us perform a similar analysis across alcohol service levels.

The story behind alcohol service levels seem to be a different than was the case for noise levels. Restaurants with greater alcohol service do not necessarily have more Yelp stars on average than those with less alcohol service. As one can see on the plot below, restaurants that only offer beer and wine instead of a full bar almost always consistently outperform restaurants with a full bar alcohol service and this difference becomes much greater at the highest price range 4. However, in the case of more expensive 3-4 price range restaurants, restaurants that offer at least beer and wine outperform restaurants that do not provide alcohol by 1 whole star!

Now, we have analyzed so many different relationships between price range and stars. I wonder which of the variables we analyzed earlier have the most impact on the Yelp stars an operating restaurant in North America might receive. We are going to do this by creating a linear model that takes into account all the other variables we explored as independent variables with stars as the dependent variable.

As we had seen in some of the earlier regressions and/or analyses, increased price ranges, being open, having no alcohol service or a full bar, having a higher review count and having lower noise levels were correlated with a higher rating. Other new relationships include the fact that we never looked at in its relationship to Yelp stars were restaurant dining options, in which having table service correlated highly with stars, though having takeout apparently is not.

Nonetheless, the percentage of variance (6.5%) explained by this model is not very high, and this suggests that many other variables such as food quality, type of cuisine, recommendation from a friend were etc. could help to improve this model.


Call:
lm(formula = stars ~ attributes.RestaurantsPriceRange2 + attributes.NoiseLevel + 
    attributes.Alcohol + review_count + is_open + attributes.RestaurantsGoodForGroups + 
    attributes.RestaurantsAttire + attributes.RestaurantsDelivery + 
    attributes.RestaurantsTakeOut + attributes.RestaurantsTableService, 
    data = subset(rest_lm_stars))

Residuals:
    Min      1Q  Median      3Q     Max 
-3.5869 -0.4557  0.0315  0.4864  2.1515 

Coefficients:
                                          Estimate Std. Error t value Pr(>|t|)    
(Intercept)                              3.506e+00  2.984e-02 117.473  < 2e-16 ***
attributes.RestaurantsPriceRange2        1.947e-02  8.474e-03   2.297   0.0216 *  
attributes.NoiseLevelloud               -2.558e-01  1.450e-02 -17.640  < 2e-16 ***
attributes.NoiseLevelquiet               1.182e-01  9.837e-03  12.017  < 2e-16 ***
attributes.NoiseLevelvery_loud          -4.734e-01  2.430e-02 -19.484  < 2e-16 ***
attributes.Alcoholfull_bar              -1.314e-01  1.233e-02 -10.653  < 2e-16 ***
attributes.Alcoholnone                  -7.692e-02  1.241e-02  -6.197 5.83e-10 ***
review_count                             5.794e-04  2.257e-05  25.671  < 2e-16 ***
is_open                                  7.156e-02  9.461e-03   7.564 4.03e-14 ***
attributes.RestaurantsGoodForGroupsTRUE -3.226e-02  1.287e-02  -2.506   0.0122 *  
attributes.RestaurantsAttiredressy       1.632e-01  2.569e-02   6.355 2.12e-10 ***
attributes.RestaurantsAttireformal      -2.339e-01  1.014e-01  -2.307   0.0211 *  
attributes.RestaurantsDeliveryTRUE       4.382e-04  9.538e-03   0.046   0.9634    
attributes.RestaurantsTakeOutTRUE       -9.582e-02  1.770e-02  -5.415 6.18e-08 ***
attributes.RestaurantsTableServiceTRUE   9.086e-02  1.054e-02   8.623  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.6768 on 31050 degrees of freedom
  (988 observations deleted due to missingness)
Multiple R-squared:  0.06591,   Adjusted R-squared:  0.06549 
F-statistic: 156.5 on 14 and 31050 DF,  p-value: < 2.2e-16

On the other hand, when a linear model is built with the independent variable being stars and it is used to predict the price range of a restaurant, we find that the variables chosen do a fairly good job at predicting how expensive a restaurant will be, as over 46% of the variance in the model is explained by these variables alone.


Call:
lm(formula = attributes.RestaurantsPriceRange2 ~ stars + attributes.NoiseLevel + 
    attributes.Alcohol + review_count + is_open + attributes.RestaurantsGoodForGroups + 
    attributes.RestaurantsAttire + attributes.RestaurantsDelivery + 
    attributes.RestaurantsTakeOut + attributes.RestaurantsTableService, 
    data = subset(rest_lm_stars))

Residuals:
     Min       1Q   Median       3Q      Max 
-1.96040 -0.24004  0.00653  0.21065  2.84970 

Coefficients:
                                          Estimate Std. Error t value Pr(>|t|)    
(Intercept)                              1.906e+00  2.145e-02  88.871  < 2e-16 ***
stars                                    8.729e-03  3.800e-03   2.297  0.02162 *  
attributes.NoiseLevelloud                4.592e-03  9.761e-03   0.470  0.63803    
attributes.NoiseLevelquiet               1.557e-02  6.602e-03   2.358  0.01837 *  
attributes.NoiseLevelvery_loud           5.147e-02  1.637e-02   3.145  0.00166 ** 
attributes.Alcoholfull_bar               2.000e-01  8.194e-03  24.409  < 2e-16 ***
attributes.Alcoholnone                  -2.618e-01  8.183e-03 -31.997  < 2e-16 ***
review_count                             1.671e-04  1.524e-05  10.961  < 2e-16 ***
is_open                                 -1.966e-02  6.341e-03  -3.101  0.00193 ** 
attributes.RestaurantsGoodForGroupsTRUE -7.245e-02  8.612e-03  -8.413  < 2e-16 ***
attributes.RestaurantsAttiredressy       8.686e-01  1.649e-02  52.666  < 2e-16 ***
attributes.RestaurantsAttireformal       5.794e-01  6.782e-02   8.543  < 2e-16 ***
attributes.RestaurantsDeliveryTRUE       5.755e-02  6.379e-03   9.022  < 2e-16 ***
attributes.RestaurantsTakeOutTRUE       -4.176e-01  1.162e-02 -35.945  < 2e-16 ***
attributes.RestaurantsTableServiceTRUE   3.088e-01  6.844e-03  45.116  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.4532 on 31050 degrees of freedom
  (988 observations deleted due to missingness)
Multiple R-squared:  0.4637,    Adjusted R-squared:  0.4635 
F-statistic:  1918 on 14 and 31050 DF,  p-value: < 2.2e-16

Multivariate Analysis

Talk about some of the relationships you observed in this part of the investigation. Were there features that strengthened each other in terms of looking at your feature(s) of interest?

  1. In Toronto and Phoenix, restaurants of varying noise levels are all over the city.

  2. In terms of alcohol service, the suburban areas of Toronto and Phoenix had less alcohol service in terms of full bar or beer and wine than in the downtown core while for Montreal, full bar alcohol service was virtually everywhere in the city.

  3. Places that were good for dinner were found all over Phoenix, while in Toronto, the highest concentrations were found in the downtown core and in the central thoroughfare, and in Montreal, dinner places were onlly found in the downtown core.

  4. Holding price range constant, between 80-90% of restaurants were rated between 3.5 to 4.5 stars.

  5. Restaurants that had noisier atmospheres had lower average stars than quieter ones and this was true across all price ranges.

Were there any interesting or surprising interactions between features?

One thing that I found interesting was that restaurants that only served beer and wine tended to do better in terms of Yelp stars than those that had full bar alcohol service.

OPTIONAL: Did you create any models with your dataset? Discuss the strengths and limitations of your model.

I created two linear models that examined the impact of the variables I discussed earlier on price range and stars. The R-squared for the linear model that predicted stars was only around 6%, meaning that were far more features that could have been better for the model even if the relationships in the model were found to be mostly statistically significant and correlated well with trends we saw earlier in the plots analysis. However, the amount of variance explained by the linear model on price range performed substantially better with 46% of variance being explained by the model.

Final Plots and Summary

Description One:

The majority of operating establishments in the plot below were rated between 3 to 5 stars, with a peak at 4 stars where almost 20% of establishments achieved this rating. Very few establishments (less than 10%) that remained operating were rated between 1 to 2 stars.

Plot One:

Description Two:

We defined value earlier as stars divided by price range, which gives us the amount of value that we derive for a given price that we pay for our food at an operating restaurant. In the graph above, we find that when it comes to getting the most “bang for your buck”, the cities of the Phoenix metropolitan area (except for Scottsdale) are the best for extracting maximum value in your dining experience for the amount of money that you pay.

Plot Two:

Description Three:

Across all North American states, it seems that very few restaurants are able to get a perfect 5 star rating. That being said, the number of restaurants that were rated 2 stars or less were also negligible as well. Almost all restaurants are clustered between 3 stars to 4.5 stars.

Plot 3:

Reflection

The Yelp academic data set on businesses contain information on over 150 thousand establishments across 101 variables within North America and beyond. Although the analysis was done on the whole data set from time to time, I was mainly interested in operating restaurants within North America which brought this number down to around 26-27 thousand establishments. But even so, I was able to perform a wide variety of analyses in terms of exploring the relationship between price, Yelp stars, review count among many other variables across a wide range of geographies on a state and city level. In this process, I created many plots and maps, calculated summary statistics and employed linear models to explore this rich and informative data set.

There was a clear trend between price range and stars, with restaurants in higher price ranges generally receiving much higher Yelp star ratings. That being said, having a higher Yelp star rating did not necessarly translate into value, as we saw that cities such as Montreal which scored highly on both indicators ended performing the worst compared to other cities when it came to the value per dollar spent. One other important point is that restaurants in more expensive price ranges tend to be located in downtown areas, though in the case of the Phoenix metropolitan area, these were found mainly in Scottsdale (a suburb to the east).

Another interesting insight is that across all price ranges, noisier restaurants tended to be rated more poorly than those that were quieter. Restaurants of all noise levels were distributed throughout the cities analyzed, and there was generally not one area where you could find restaurants of a specific noise level.

Although I expected many establishments to have low review counts, I was quite surprised to find that the median number of reviews per establishment was so low, and that the dispersion of review counts across different establishments was so large. Something that did not surprise me, however, was that almost all closed establishments tended to have a lower review count. Finally, one last thing that I found interesting was that restaurants that served only beer and wine tended to be rated higher than those that had full bar service.

One of the biggest limitations of the data set was the lack of data from other North American cities/states. It is not known why or how these cities were chosen, and it is not clear if every establishment in these cities is covered in the data set. The variables present in this data set also skewed heavily towards the analysis of restaurants, so that other Yelp-rated establishments such as spas, salons and hotels were harder to analyze. It would be interesting to have a much larger selection of cities/states to choose from, and to be able to test the linear models above to see if the relationships end up becoming stronger or weaker with a richer data set.

LS0tDQp0aXRsZTogIlllbHAgQnVzaW5lc3MgRGF0YSBFeHBsb3JhdGlvbiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KYXV0aG9yOiAiSmFja2llIFRhbmciDQotLS0NCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhY2thZ2VzfQ0KcmVxdWlyZShrbml0cikgIyByZXF1aXJlZCBmb3Iga25pdHRpbmcgZnJvbSBybWQgdG8gbWQNCnJlcXVpcmUobWFya2Rvd24pICMgcmVxdWlyZWQgZm9yIG1kIHRvIGh0bWwgDQprbml0KCd5ZWxwX2VkYV9wcm9qZWN0LnJtZCcsICd5ZWxwX2VkYV9wcm9qZWN0Lm1kJykgIyBjcmVhdGVzIG1kIGZpbGUNCm1hcmtkb3duVG9IVE1MKCd5ZWxwX2VkYV9wcm9qZWN0Lm1kJywgJ3llbHBfZWRhX3Byb2plY3QuaHRtbCcpICMgY3JlYXRlcyBodG1sIGZpbGUNCmJyb3dzZVVSTChwYXN0ZSgnZmlsZTovLycsIGZpbGUucGF0aChnZXR3ZCgpLCd5ZWxwX2VkYV9wcm9qZWN0Lmh0bWwnKSwgc2VwPScnKSkgIyBvcGVuIGZpbGUgaW4gYnJvd3NlciANCmBgYA0KDQoNClRoaXMgcmVwb3J0IGNvbnRhaW5zIGNvZGUsIHBsb3RzLCBtYXBzIGFuZCBhbmFseXNlcyB0aGF0IGV4cGxvcmUgWWVscCdzIGFjYWRlbWljIGRhdGEgc2V0IG9uIGJ1c2luZXNzZXMgY292ZXJpbmcgb3ZlciAxNTAsMDAwIFllbHAtcmF0ZWQgZXN0YWJsaXNobWVudHMgYWNyb3NzIG92ZXIgMTAwIHZhcmlhYmxlcy4NCg0KIyBVbml2YXJpYXRlIFBsb3RzIFNlY3Rpb24NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCg0KI0xvYWRzIGluIHBhY2thZ2VzIHdlIG5lZWQgZm9yIHByb2R1Y2luZyBwbG90cyBhbmQgZGF0YSBzZXRzDQpsaWJyYXJ5KG1hZ3JpdHRyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShtYXBzKQ0KbGlicmFyeShkcGx5cikNCg0KbGlicmFyeShnZ21hcCkNCmxpYnJhcnkobWFwdG9vbHMpDQpsaWJyYXJ5KGdyaWRFeHRyYSkNCmxpYnJhcnkoanNvbmxpdGUpDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikNCg0KcmVxdWlyZShkcGx5cik7IHJlcXVpcmUoUkNvbG9yQnJld2VyKTsgcmVxdWlyZShnZ3Bsb3QyKTsNCnJlcXVpcmUobWFwdG9vbHMpDQoNCnllbHAgPC0gc3RyZWFtX2luKGZpbGUNCigiQzovL1VzZXJzLy9KYWNraWUvL0Rvd25sb2Fkcy8veWVscF9kYXRhc2V0Ly9idXNpbmVzcy5qc29uIikpDQoNCnllbHBfZmxhdCA8LSBmbGF0dGVuKHllbHApDQoNCiNUaGVyZSBhcmUgMTU2LDYzOSBvYnNlcnZhdGlvbnMgaW4gdGhpcyBkYXRhc2V0Lg0KbnJvdyh5ZWxwX2ZsYXQpDQoNCmBgYA0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KI1RoZXJlIGFyZSAxMDEgdmFyaWFibGVzIGluIHRoaXMgZGF0YXNldC4NCm5jb2woeWVscF9mbGF0KQ0KYGBgDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCiNTdW1tYXJ5IG9mIHRoZSBkaXN0cmlidXRpb24gb2YgdmFsdWVzIHdpdGhpbiBlYWNoIHZhcmlhYmxlDQojc3VtbWFyeSh5ZWxwX2ZsYXQpDQoNCmBgYA0KDQpUaGUgZ29hbHMgb2YgbXkgZXhwbG9yYXRvcnkgYW5hbHlzaXMgb2YgdGhlIFllbHAgKGFjYWRlbWljKSBidXNpbmVzcyBkYXRhIHNldCB3aWxsIGJlIGFzIGZvbGxvd3MuDQoNCjEpIEVzdGFibGlzaCBhbiB1bmRlcnN0YW5kaW5nIG9mIHRocmVlIGtleSB2YXJpYWJsZXM6IHJldmlldyBjb3VudCwgcHJpY2UgcmFuZ2UgYW5kIHN0YXJzIChyYXRpbmdzKQ0KMikgVW5kZXJzdGFuZCBhbmQgdmlzdWFsaXplIGhvdyBnZW9ncmFwaHksIG9wZXJhdGluZyBzdGF0dXMgKG9wZW4gb3IgY2xvc2VkKSwgYWxjb2hvbCBzZXJ2aWNlIGFuZCBub2lzZSBsZXZlbHMgY2FuIGVuZCB1cCBhZmZlY3RpbmcgdGhlIHRocmVlIGtleSB2YXJpYWJsZXMgZXhwbG9yZWQgaW4gdGhpcyBkYXRhIHNldDogcmV2aWV3IGNvdW50LCBwcmljZSByYW5nZSBhbmQgc3RhcnMNCjMpIFBlcmZvcm0gdGhlIGFuYWx5c2lzIGFzIGV4cGxhaW5lZCBpbiAxKSBhbmQgMikgb24gcGFydGljdWxhciBzZWdtZW50cyBvZiBZZWxwIGVzdGFibGlzaG1lbnRzIChzdWNoIGFzIG9wZXJhdGluZyByZXN0YXVyYW50cyBpbiBOb3J0aCBBbWVyaWNhKQ0KDQoNCkluIHRoZSB1bml2YXJpYXRlIHBsb3RzIHNlY3Rpb24sIHRoZSBlbXBoYXNpcyB3aWxsIGJlIG9uIGFuYWx5c2luZyBzb21lIG9mIHRoZSBrZXkgdmFyaWFibGVzIHRoYXQgd2lsbCBiZSBkaXNjdXNzZWQgbGF0ZXIgaW4gdGhlIGJpdmFyaWF0ZSBhbmQgbXVsdGl2YXJpYXRlIGFuYWx5c2lzIHN1Y2ggYXMgcHJpY2UgcmFuZ2UsIHN0YXJzLCBhbmQgcmV2aWV3IGNvdW50IGFsb25nIHdpdGggb3RoZXIgdmFyaWFibGVzIHN1Y2ggYXMgdGhlIGdlb2dyYXBoaWMgZGlzcGVyc2lvbiBvZiBlc3RhYmxpc2htZW50cyBhcyB3ZWxsIGFzIHNvbWUgaW5mb3JtYXRpb24gb24gYWxjb2hvbCBzZXJ2aWNlIGFuZCBub2lzZSBsZXZlbHMuDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGggPSA3LjV9DQojVW5pdmFyaWF0ZSBwbG90cyBzZWN0aW9uDQoNCg0KI0Z1bmN0aW9uIGJlbG93IGlzIHRvIGdyb3VwIGVzdGFibGlzaG1lbnRzIGJhc2VkIG9uIHN0YXJzIGFjcm9zcyBhbGwgZ2VvZ3JhcGhpZXMNCiNUaGVuIGl0IHN1bXMgZXN0YWJsaXNobWVudHMgYWNjb3JkaW5nIHRvIGVhY2ggc3RhciBsZXZlbCBhbmQgY2FsY3VsYXRlcyBhIHBlcmNlbnQgb2YgdG90YWwgZXN0YWJsaXNobWVudHMNCnllbHBfc3RhcnMgPC0gZnVuY3Rpb24oZGF0YXNldCwgdGl0bGUxKSB7DQp5ZWxwc3RhciA8LSBkYXRhc2V0JT4lDQpncm91cF9ieShzdGFycykgJT4lDQpzdW1tYXJpc2UodG90YWxfYnlfc3RhciA9IG4oKSkgJT4lDQptdXRhdGUodG90YWwgPSBzdW0odG90YWxfYnlfc3RhcikpICU+JSANCm11dGF0ZShwZXJjZW50ID0gcm91bmQoKHRvdGFsX2J5X3N0YXIgLyB0b3RhbCkqMTAwLCAxKSkNCg0KDQojQmVsb3cgaXMgYSB1bml2YXJpYXRlIHBsb3Qgc2hvd2luZyB0aGUgZGlzdHJpYnV0aW9uIG9mIHN0YXJzIGFjcm9zcyBhbGwgZXN0YWJsaXNobWVudHMNCmdncGxvdCh5ZWxwc3RhciwgYWVzKHggPSBzdGFycywgeSA9IHBlcmNlbnQpKSArIA0KZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAnbGlnaHRibHVlJykgKyBsYWJzKHg9J1N0YXJzIChyYXRpbmdzKScpICsNCiAgbGFicyggeSA9ICdQZXJjZW50IG9mIHRvdGFsIHJhdGluZ3MnKSArbGFicyh0aXRsZSA9ICB0aXRsZTEpICsgDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMSwgNSwgMC41KSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltID0gYygwLCAyNSkpKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgICsNCiBnZW9tX3RleHQoYWVzKGxhYmVsPXBlcmNlbnQpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMSksIA0KICAgICAgICAgICB2anVzdCA9IC0wLjUsIHNpemUgPSA0KSANCn0NCg0KeWVscF9zdGFycyh5ZWxwX2ZsYXQsICdEaXN0cmlidXRpb24gb2YgWWVscCBzdGFycyBhY3Jvc3MgYWxsIGVzdGFibGlzaG1lbnRzJykNCg0KYGBgDQoNCk9uZSBvZiB0aGUgZmlyc3QgdGhpbmdzIHRoYXQgSSB3YW50IHRvIGRvIHRvIHN0YXJ0IG15IGFuYWx5c2lzIGlzIHRvIGxvb2sgYXQgc3RhcnMgKHJhdGluZ3MpIGFjcm9zcyBhbGwgZXN0YWJsaXNobWVudHMuDQoNCkZyb20gdGhlIGhpc3RvZ3JhbSBiZWxvdywgaXQgc2VlbXMgdGhhdCBtb3N0IHJhdGluZ3MgYXJlIGNlbnRyZWQgYXJvdW5kIDMuNSB0byA0IHN0YXJzLCB3aGljaCBzZWVtcyBxdWl0ZSBjb25zaXN0ZW50IHdpdGggbXkgcHJpb3Iga25vd2xlZGdlIG9mIFllbHAgcmV2aWV3cy4gR2VuZXJhbGx5LCBwZW9wbGUgdGVuZCB0byBnaXZlIGZhaXJseSBnb29kIHJldmlld3MhDQoNCk9mIGNvdXJzZSwgdGhlIGhpc3RvZ3JhbSBpbmNsdWRlcyBib3RoIG9wZW4gYW5kIGNsb3NlZCBlc3RhYmxpc2htZW50cywgYW5kIHdlIGtub3cgdGhhdCBnZW5lcmFsbHkgc3BlYWtpbmcgZXN0YWJsaXNobWVudHMgdGhhdCBoYXZlIGNsb3NlZCBtYXkgaGF2ZSBjbG9zZWQgZHVlIHRvIHBvb3IgYnVzaW5lc3MsIHBhcnRseSBiZWNhdXNlIG9mIHBvb3IgcmV2aWV3cyBhbmQgb3BpbmlvbnMgb2YgdGhlIGVzdGFibGlzaG1lbnQuIFdoYXQgaWYgd2Ugb25seSBhY2NvdW50ZWQgZm9yIGVzdGFibGlzaG1lbnRzIHRoYXQgd2VyZSBjbG9zZWQgYW5kIG5vIGxvbmdlciBvcGVyYXRpbmc/IFdvdWxkIHRoaXMgZGlzdHJpYnV0aW9uIGNoYW5nZT8NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDcuNX0NCg0KI0NvZGUgYmVsb3cgaXMgdG8gZ3JvdXAgZXN0YWJsaXNobWVudHMgYmFzZWQgb24gc3RhcnMgYWNyb3NzIGFsbCBnZW9ncmFwaGllcw0KDQp5ZWxwX29wZW4gPC0gc3Vic2V0KHllbHBfZmxhdCwgaXNfb3BlbiA9PSAwKQ0KDQp5ZWxwX3N0YXJzKHllbHBfb3BlbiwgJ0Rpc3RyaWJ1dGlvbiBvZiBZZWxwIHN0YXJzIGFjcm9zcyBjbG9zZWQgZXN0YWJsaXNobWVudHMnKQ0KYGBgDQoNCkFzIHdlIGNhbiBzZWUgZnJvbSB0aGUgaGlzdG9ncmFtIHNob3dpbmcgdGhlIGRpc3RyaWJ1dGlvbiBvZiBzdGFycyBhY3Jvc3MgY2xvc2VkIGVzdGFibGlzaG1lbnRzLCB0aGUgZGlzdHJpYnV0aW9uIGluIHRoZSBsb3dlciBlbmRzIGRvIG5vdCBjaGFuZ2UgbXVjaC4gSG93ZXZlciwgd2UgY2FuIHNlZSB0aGF0IHRoZXJlIGlzIGEgc3Vic3RhbnRpYWwgZGVjbGluZSBpbiB0aGUgcHJvcG9ydGlvbiBvZiBjbG9zZWQgZXN0YWJsaXNobWVudHMgdGhhdCB3ZXJlIHJhdGVkIDQuNSBhbmQgNSBzdGFycy4gVGhpcyBpcyBkZWZpbml0ZWx5IGEgcGxhdXNpYmxlIGV4cGxhbmF0aW9uIGFzIGVzdGFibGlzaG1lbnRzIHRoYXQgYXJlIHJhdGVkIGhpZ2hseSBnZW5lcmFsbHkgZG8gbm90IGNsb3NlIHdpdGhvdXQgZ29vZCByZWFzb24uDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGggPSA3LjV9DQoNCiNJIG9ubHkgaW5jbHVkZSB0aGVzZSBzdGF0ZXMsIGJlY2F1c2UgSSBhbSBzb2xlbHkgaW50ZXJlc3RlZCBpbiBhbmFseXppbmcgTm9ydGggQW1lcmljYSAoYXQgbGVhc3Qgd2hlbiBjYXRlZ29yaXppbmcgYnkgc3RhdGUsIHRob3VnaCB0aGVyZSBhcmUgc29tZSBhbmFseXNlcyB3aGljaCBtYXkgaW5jbHVkZSBhbGwgZXN0YWJsaXNobWVudHMgaW4gZ2VuZXJhbCksIGFuZCBub3QgaW4gc3RhdGVzIGluIEdlcm1hbnkgb3IgYW55IG90aGVyIHRlcnJpdG9yeS4gQWZ0ZXIgaGF2aW5nIGdvbmUgdGhyb3VnaCB0aGUgbGlzdCBvZiBzdGF0ZXMgcmVwcmVzZW50ZWQgaW4gdGhlIGRhdGEgc2V0LCBvbmx5IHRoZSBzdGF0ZXMgYmVsb3cgcmVwcmVzZW50ZWQgdGhvc2Ugb2YgTm9ydGggQW1lcmljYQ0KDQoNCnllbHBfZmxhdDEgPC0gc3Vic2V0KHllbHBfZmxhdCwgeWVscF9mbGF0JHN0YXRlID09ICdBWicgfCANCiAgeWVscF9mbGF0JHN0YXRlID09ICdXSScgfCB5ZWxwX2ZsYXQkc3RhdGUgPT0gJ05DJyB8IA0KICB5ZWxwX2ZsYXQkc3RhdGUgPT0gJ05WJyB8IHllbHBfZmxhdCRzdGF0ZSA9PSAnT0gnIHwgDQogIHllbHBfZmxhdCRzdGF0ZSA9PSAnT04nIHwgeWVscF9mbGF0JHN0YXRlID09ICdQQScgfCANCiAgeWVscF9mbGF0JHN0YXRlID09ICdRQycgfCB5ZWxwX2ZsYXQkc3RhdGUgPT0gJ1NDJyApDQoNCiNGdW5jdGlvbiBiZWxvdyBjcmVhdGVzIGEgaGlzdG9ncmFtIG9mIHRoZSBudW1iZXIgb2YgZXN0YWJsaXNobWVudHMgYnkgYSBnZW9ncmFwaGljIGVudGl0eQ0KI0ZpcnN0IGl0IGdyb3VwcyB0aGUgZGF0YXNldCBieSB2YXIxIHJlcHJlc2VudGluZyB0aGUgZ2VvZ3JhcGh5IGFuZCBjcmVhdGVzIGFuZCBzdW1zIHRoZSBudW1iZXIgDQojb2YgZXN0YWJsaXNobWVudHMNCmVzdGFiX2NvdW50IDwtIGZ1bmN0aW9uKGRhdGFzZXQsIHZhcjEsIGksIHRpdGxlbmFtZSwgY29sb3VyMSkgew0KICB2YXIxIDwtIGVucXVvKHZhcjEpDQogIGNvdW50X3N0YXRlX3Jldmlld3MgPC0gZGF0YXNldCAlPiUNCiAgZ3JvdXBfYnkoISF2YXIxKSU+JQ0KICBzdW1tYXJpc2Uobj1uKCkpDQoNCiNQbG90IHRoZSBudW1iZXIgb2YgZXN0YWJsaXNobWVudHMgcmF0ZWQgb24gWWVscCBieSBzdGF0ZSAoaW4gZGVzY2VuZGluZyBvcmRlcikNCmdncGxvdChjb3VudF9zdGF0ZV9yZXZpZXdzLCBhZXMocmVvcmRlcihzdGF0ZSwgLW4pLCBuKSkgKyANCmdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gY29sb3VyMSkgKyBsYWJzKHg9J3N0YXRlJykgKyANCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbSA9IGMoMCwgaSkpICsgDQogIGxhYnMoeSA9ICJOdW1iZXIgb2YgZXN0YWJsaXNobWVudHMiKSArIA0KICBsYWJzKHRpdGxlPSB0aXRsZW5hbWUpICsgDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQ0KfQ0KZXN0YWJfY291bnQoeWVscF9mbGF0MSwgc3RhdGUsIDUwMDAwLCANCiAgICAgICAgICAgICJOdW1iZXIgb2YgZXN0YWJsaXNobWVudHMgYnkgc3RhdGUiLCAiZGFya2dyZWVuIikNCg0KYGBgDQoNClRoaXMgWWVscCBkYXRhIHNldCBkb2VzIG5vdCBzZWVtIHRvIGhhdmUgYW4gZXF1YWwgcmVwcmVzZW50YXRpb24gb2YgdGhlIG51bWJlciBvZiBlc3RhYmxpc2htZW50cyBieSBnZW9ncmFwaHkgZXNwZWNpYWxseSB3aGVuIHdlIGFjY291bnQgZm9yIHRoZSBkaWZmZXJlbmNlcyBpbiBwb3B1bGF0aW9uLg0KVGhlIG1ham9yaXR5IG9mIGVzdGFibGlzaG1lbnRzIGluIHRoaXMgZGF0YSBzZXQgYXJlIGluIEFyaXpvbmEsIE9udGFyaW8gYW5kIE5ldmFkYSwgd2l0aCBzbWFsbGVyIG51bWJlcnMgb2YgcmVwcmVzZW50YXRpb24gaW4gb3RoZXIgc3RhdGVzIHN1Y2ggYXMgTm9ydGggQ2Fyb2xpbmEsIE9oaW8gYW5kIFF1ZWJlYy4gSG93ZXZlciwgQXJpem9uYSBoYXMgYSBwb3B1bGF0aW9uIG9mIGFsbW9zdCA3IG1pbGxpb24gd2hpY2ggaXMgaGFsZiBvZiBPbnRhcmlvJ3MgcG9wdWxhdGlvbiBvZiAxNCBtaWxsaW9uLCB5ZXQgaGFzIHR3aWNlIHRoZSBudW1iZXIgb2YgZXN0YWJsaXNobWVudHMgYmVpbmcgcmVwcmVzZW50ZWQuIEZ1cnRoZXIsIHRoZXJlIGFyZSBvbmx5IDkgTm9ydGggQW1lcmljYW4gc3RhdGVzIGNvdmVyZWQgaW4gdGhlIGRhdGEgc2V0LCBidXQgdGhlcmUgYXJlIG1vcmUgdGhhbiA1MCBzdGF0ZXMgaW4gdGhlIFVuaXRlZCBTdGF0ZXMgYW5kIG1vcmUgdGhhbiAxMCB3aXRoaW4gQ2FuYWRhLg0KDQpJbiBhbnkgY2FzZSwgdGhlIGFuYWx5c2lzIGZvciByZXZpZXcgY291bnQgYW5kIHN0YXJzIGlzIGZhciBmcm9tIGNvbXBsZXRlLCBob3dldmVyLCB3ZSB3aWxsIHJldmlzaXQgdGhlc2UgdHdvIHZhcmlhYmxlcyBpbiBncmVhdGVyIGRldGFpbCBpbiBsYXRlciBzZWN0aW9ucy4NCg0KRm9yIG5vdywgbGV0IHVzIGNvbmNlbnRyYXRlIG9uIGxvb2tpbmcgYXQgbXkgZmF2b3VyaXRlIHBhcnQgb2YgWWVscCByYXRpbmdzLCB3aGljaCBhcmUgcmVzdGF1cmFudHMhDQpJbiB0aGUgZm9sbG93aW5nIHNlY3Rpb25zIGFuZCBhbmFseXNpcywgSSB3aWxsIGNvbmNlbnRyYXRlIGFsbW9zdCBleGNsdXNpdmVseSBvbiBvcGVyYXRpbmcgcmVzdGF1cmFudHMgbG9jYXRlZCB3aXRoaW4gTm9ydGggQW1lcmljYS4NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCg0KDQojVGhpcyBpcyBzdWJzZXR0ZWQgb25seSBmb3Igb3BlcmF0aW5nIHJlc3RhdXJhbnRzIGluIE5vcnRoIEFtZXJpY2FuIHN0YXRlcywgZXN0YWJsaXNobWVudHMgYXJlIHJlc3RhdXJhbnRzIHdoZW4gcHJpY2UgcmFuZ2UsIHRha2Ugb3V0LCBkZWxpdmVyeSBhbmQgdGFibGUgc2VydmljZSBhdHRyaWJ1dGVzIGFyZSBub24tbnVsbC4NCg0KcmVzdF8wIDwtIHN1YnNldCh5ZWxwX2ZsYXQxLCBpc19vcGVuID09IDEgJiAhaXMubmEoYXR0cmlidXRlcy5SZXN0YXVyYW50c1ByaWNlUmFuZ2UyKSAmICFpcy5uYShhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzVGFrZU91dCkgJiAhaXMubmEoYXR0cmlidXRlcy5SZXN0YXVyYW50c0RlbGl2ZXJ5KSAmICFpcy5uYShhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzVGFibGVTZXJ2aWNlKSkNCg0KbnJvdyhyZXN0XzApDQpgYGANCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCm5yb3coeWVscF9mbGF0MSkNCg0KYGBgDQoNCldoZW4gd2UgcGFydGl0aW9uIG9ubHkgZm9yIE5vcnRoIEFtZXJpY2FuIHJlc3RhdXJhbnRzIHRoYXQgYXJlIG9wZXJhdGluZyBpbiB0aGlzIFllbHAgZGF0YSBzZXQsIHdlIGZpbmQgdGhhdCB0aGUgbnVtYmVyIGlzIG9ubHkgMjYsNjQyLiBPdXQgb2YgMTU2LDYzOSBlc3RhYmxpc2htZW50cywgbXkgYXJlYSBvZiBpbnRlcmVzdCBvbmx5IHJlcHJlc2VudHMgYXBwcm94aW1hdGVseSAxNyUgb2YgYWxsIGVzdGFibGlzaG1lbnRzLiBXaGVuIHdlIHBhcnRpdGlvbiBvbmx5IGZvciBOb3J0aCBBbWVyaWNhbiBzdGF0ZXMgd2hpY2ggaGF2ZSBhIHRvdGFsIG9mIDE0Nyw2NTggZXN0YWJsaXNobWVudHMsIHRoaXMgcGVyY2VudGFnZSBnb2VzIHVwIG9ubHkgc2xpZ2h0bHkgdG8gMTglICh0aGUgbnVtYmVyIG9mIGVzdGFibGlzaG1lbnRzIG91dHNpZGUgTm9ydGggQW1lcmljYSBhcmUgbWluaW1hbCkuIA0KDQpUaGlzIGlzIG9idmlvdXNseSBiZWNhdXNlIHRoZXJlIGFyZSBtYW55IG90aGVyIHN1Y2ggZXN0YWJsaXNobWVudHMgc3VjaCBhcyBuYWlsIHNhbG9ucywgYW11c2VtZW50IHBhcmtzLCBjb21tdW5pdHkgY2VudHJlcywgc3BhcywgYWxvbmcgd2l0aCBjbG9zZWQgcmVzdGF1cmFudHMgb3IgcmVzdGF1cmFudHMgb3V0c2lkZSBvZiBOb3J0aCBBbWVyaWNhIHRoYXQgYXJlIG5vdCBpbmNsdWRlZCBpbiBteSBhbmFseXNpcy4NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDcuNX0NCg0KDQojUGxvdCB0aGUgbnVtYmVyIG9mIG9wZXJhdGluZyByZXN0YXVyYW50cyByYXRlZCBvbiBZZWxwIGJ5IHN0YXRlIChpbiBkZXNjZW5kaW5nIG9yZGVyKSBieSBjYWxsaW5nIGZ1bmN0aW9uIGVzdGFiX2NvdW50IGVhcmxpZXIgd2hpY2ggY3JlYXRlcyBhIHBsb3Qgb2YgdGhlIG51bWJlciBvZiBlc3RhYmxpc2htZW50cyBieSBzdGF0ZQ0KDQoNCmVzdGFiX2NvdW50KHJlc3RfMCwgc3RhdGUsIDgwMDAsIA0KICAgICAgICAgICAgIk51bWJlciBvZiBvcGVyYXRpbmcgcmVzdGF1cmFudHMgYnkgc3RhdGUiLCAicHVycGxlIikNCg0KYGBgDQoNCkFzIHdlIHNhdyBlYXJsaWVyLCB3aGlsZSB0aGVyZSB3ZXJlIGxhcmdlIHZhcmlhbmNlcyBpbiB0aGUgbnVtYmVyIG9mIGVzdGFibGlzaG1lbnRzIGluIHRoZSBkYXRhIHNldCBieSBzdGF0ZSwgaW4gdGVybXMgb2Ygb3BlcmF0aW5nIHJlc3RhdXJhbnRzLCB0aGVyZSBzZWVtcyBtb3JlIG9mIGFuIGV2ZW4gc3ByZWFkIG91dCBhY3Jvc3Mgc3RhdGVzIHdpdGggbGVzcyBvZiBhIGhlYXZ5IGVtcGhhc2lzIG9uIE5ldmFkYSBhbmQgQXJpem9uYS4NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDcuNX0NCg0KI0FsdGhvdWdoIFdJIGFuZCBTQyBhcmUgYWxzbyByZXByZXNlbnRlZCBpbiB0aGUgTm9ydGggQW1lcmljYW4gc3RhdGVzIGluIHRoZSBZZWxwIGRhdGEgc2V0LCBJIGV4Y2x1ZGUgdGhlIGNpdGllcyBvZiBGb3J0IE1pbGwsIFNDIGR1ZSB0byBpdHMgbGFjayBvZiBpbmZvcm1hdGlvbg0KDQp5ZWxwX2ZsYXQyIDwtIHN1YnNldCh5ZWxwX2ZsYXQsIHllbHBfZmxhdCRjaXR5ID09ICJDbGV2ZWxhbmQiIHwgDQogIHllbHBfZmxhdCRjaXR5ID09ICJDaGFybG90dGUiIHwgeWVscF9mbGF0JGNpdHkgPT0gIkxhcyBWZWdhcyIgfCANCiAgeWVscF9mbGF0JGNpdHkgPT0gIk1lc2EiIHwgeWVscF9mbGF0JGNpdHkgPT0gIk1lc2EiIHwgDQogIHllbHBfZmxhdCRjaXR5ID09ICJNb250culhbCIgfCB5ZWxwX2ZsYXQkY2l0eSA9PSAiUGhvZW5peCIgfCANCiAgeWVscF9mbGF0JGNpdHkgPT0gIlBpdHRzYnVyZ2giIHwgeWVscF9mbGF0JGNpdHkgPT0gIlRlbXBlIiB8IA0KICB5ZWxwX2ZsYXQkY2l0eSA9PSAiVG9yb250byIgfCB5ZWxwX2ZsYXQkY2l0eSA9PSAiU2NvdHRzZGFsZSIgfCANCiAgeWVscF9mbGF0JGNpdHkgPT0gIk1hZGlzb24iICkNCg0KI1RoaXMgcGFydGl0aW9ucyB0aGUgZGF0YSBzZXQgZnVydGhlciBieSBvbmx5IGluY2x1ZGluZyByZXN0YXVyYW50cyB0aGF0IGFyZSBvcGVuIGZvciB0aGVzZSBjaXRpZXMNCnJlc3RfY2l0eSA8LSBzdWJzZXQoeWVscF9mbGF0MiwgaXNfb3BlbiA9PSAxICYgDQogICFpcy5uYShhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIpICYgDQogICFpcy5uYShhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzVGFrZU91dCkgJiANCiAgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNEZWxpdmVyeSkgJiANCiAgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNUYWJsZVNlcnZpY2UpKQ0KDQojVGhpcyBjYWxjdWxhdGVzIHRoZSBudW1iZXIgb2Ygb3BlcmF0aW5nIHJlc3RhdXJhbnRzIGluIG1ham9yIE5vcnRoIEFtZXJpY2FuIGNpdGllcyBpbiB0aGUgZGF0YSBzZXQNCg0KcmVzdF9jaXR5X2NvdW50IDwtIHJlc3RfY2l0eSAlPiUNCmdyb3VwX2J5KGNpdHkpJT4lDQpzdW1tYXJpc2UobiA9IG4oKSkNCg0KI1Bsb3QgdGhlIG51bWJlciBvZiBvcGVyYXRpbmcgcmVzdGF1cmFudHMgcmF0ZWQgb24gWWVscCBieSBzdGF0ZSAoaW4gZGVzY2VuZGluZyBvcmRlcikNCmdncGxvdChyZXN0X2NpdHlfY291bnQsIGFlcyhyZW9yZGVyKGNpdHksIC1uKSwgbikpICsgDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gJ3B1cnBsZScpICsgbGFicyh4PSdjaXR5JykgKyANCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbSA9IGMoMCwgNTAwMCkpICsgDQogIGxhYnMoeSA9ICJOdW1iZXIgb2Ygb3BlcmF0aW5nIHJlc3RhdXJhbnRzIikgKyANCiAgbGFicyh0aXRsZT0gIk51bWJlciBvZiBvcGVyYXRpbmcgcmVzdGF1cmFudHMgYnkgY2l0eSIpICsgDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQ0KDQpgYGANCg0KVGhlIHBsb3QgYmVsb3cgc2hvd3MgdGhlIHRvcCAxMCBvciBzbyBjaXRpZXMgdGhhdCB3ZXJlIHNlbGVjdGVkIGZvciBteSBkYXRhIGFuYWx5c2lzLCBhbmQgdGhpcyB3YXMgZHVlIHRvIHRoZSBmYWN0IHRoYXQgdGhleSBoYWQgdGhlIG1vc3QgZXN0YWJsaXNobWVudHMuIE5vdCBzdXJwcmlzaW5nbHksIGFsbCB0aGUgY2l0aWVzIGFib3ZlIGFyZSB0aGUgbGFyZ2VzdCBjaXRpZXMgaW4gdGhlIHN0YXRlcyB0aGF0IHdlcmUgaW4gdGhlIHBsb3QgZWFybGllci4gV2l0aCB0aGUgZXhjZXB0aW9uIG9mIHRoZSBQaG9lbml4IG1ldHJvcG9saXRhbiBhcmVhLCB3aGljaCBjb3ZlcnMgdGhlIGNpdGllcyBvZiBQaG9lbml4LCBNZXNhLCBTY290dHNkYWxlIGFuZCBUZW1wZSwgYWxsIHRoZSBvdGhlciBjaXRpZXMgYXJlIHRoZSBvbmx5IGNpdGllcyB0aGF0IGFyZSBjb3ZlcmVkIGluIG15IGFuYWx5c2lzIHdpdGhpbiB0aGF0IHN0YXRlLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoID0gNy41fQ0KDQojSW4gbXkgYW5hbHlzaXMsIEkgbm90aWNlZCB0aGF0IHRoZXJlIHdlcmUgZW50cmllcyB0aGF0IGhhZCBwcmljZSByYW5nZSB2YWx1ZXMgZGVzcGl0ZSBiZWluZyBub3QgYSByZXN0YXVyYW50IChleC4gYSBuYWlsIHNhbG9uKSwgYW5kIHNvIHRoZSBxdWVyeSBiZWxvdyBmaWx0ZXJzIGZvciB0YWtlIG91dCwgZGVsaXZlcnksIGFuZCB0YWJsZSBzZXJ2aWNlIHZhbHVlcyBub3QgYmVpbmcgbnVsbCBpbiBhZGRpdGlvbiB0byByZXN0YXVyYW50IHByaWNlIHJhbmdlIHZhbHVlcyBub3QgYmVpbmcgbnVsbC4NCg0KDQpyZXN0X3ByaWNlcyA8LSByZXN0XzAgJT4lDQpncm91cF9ieShhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIpICU+JQ0Kc3VtbWFyaXNlKG4gPSBuKCkpICU+JQ0KbXV0YXRlKHRvdGFsID0gc3VtKG4pKSAlPiUgDQptdXRhdGUocGVyY2VudCA9IHJvdW5kKChuIC8gdG90YWwpKjEwMCwgMSkpIA0KDQoNCmdncGxvdChyZXN0X3ByaWNlcywgYWVzKHggPSBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIsIHkgPSBwZXJjZW50KSkgKyANCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAnb3JhbmdlJywgd2lkdGggPSAwLjYpICsgDQogIGxhYnMoeD0nUHJpY2UgUmFuZ2UnKSArbGFicyggeSA9ICdQZXJjZW50IG9mIHRvdGFsIG51bWJlciBvZiByZXN0YXVyYW50cycpICsNCiAgbGFicyh0aXRsZSA9ICdEaXN0cmlidXRpb24gb2YgcmVzdGF1cmFudHMgYWNyb3NzIHByaWNlIHJhbmdlcycpICsgDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMSwgNCwgMSkpICsgDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSAgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsPXBlcmNlbnQpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMSksDQogIHZqdXN0ID0gLTAuNSwgc2l6ZSA9IDQpICsgc2NhbGVfeV9jb250aW51b3VzKGxpbSA9IGMoMCwgNjApKQ0KDQpgYGANCg0KVG8gc3RhcnQgb3VyIHVuaXZhcmlhdGUgYW5hbHlzaXMgb24gcmVzdGF1cmFudHMsIGxldCB1cyBsb29rIGF0IHRoZSBwcmljZSByYW5nZSBhY3Jvc3MgYWxsIHJlc3RhdXJhbnRzLiANCg0KQXMgd2UgY2FuIHNlZSBmcm9tIHRoZSBwbG90IGJlbG93LCB0aGUgdmFzdCBtYWpvcml0eSBvZiByZXN0YXVyYW50cyBhcmUgaW4gdGhlIDEtMiBsb3cgdG8gbWVkaXVtIHByaWNlIHJhbmdlLCB3aGlsZSBvbmx5IGEgdmVyeSBzbWFsbCBwcm9wb3J0aW9uIChhcm91bmQgNS02IHBlcmNlbnQpIGFyZSB3aGF0IHdlIHdvdWxkIGNvbnNpZGVyIHRvIGJlIHRoZSBtb3JlIGhpZ2gtZW5kIGFuZCBleHBlbnNpdmUgdHlwZSBvZiByZXN0YXVyYW50IChpbiB0aGUgMy00IHByaWNlIHJhbmdlKS4gVGhpcyBzb3J0IG9mIG1ha2VzIHNlbnNlIGJlY2F1c2UgcGxhY2VzIHN1Y2ggYXMgTWNEb25hbGRzIGFuZCBLRkMgYXJlIGZhY3RvcmVkIGludG8gdGhlIHJlc3RhdXJhbnQgY2F0ZWdvcnkgYXMgd2VsbCwgYW5kIGJ5IGZhciB0aGUgdmFzdCBtYWpvcml0eSBvZiByZXN0YXVyYW50cyBhcmUgb2YgdGhlIGZhc3QtZm9vZCBhbmQgdGFrZS1vdXQgdmFyaWV0eS4NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDcuNX0NCg0KI3NpbWlsYXIgdG8gcHJldmlvdXMgZnVuY3Rpb25zLCBidXQgdGhpcyBvbmUgZW5zdXJlcyB0aGF0IHRoZSBhbGNvaG9sIHZhcmlhYmxlIGlzIG5vdCBOQQ0KcmVzdF8xIDwtIHN1YnNldChyZXN0XzAsICFpcy5uYShhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIpICYNCiAgaXNfb3BlbiA9PSAxICYNCiAgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNUYWtlT3V0KSAmIA0KICAhaXMubmEoYXR0cmlidXRlcy5SZXN0YXVyYW50c0RlbGl2ZXJ5KSAmIA0KICAhaXMubmEoYXR0cmlidXRlcy5SZXN0YXVyYW50c1RhYmxlU2VydmljZSkgJiAhaXMubmEoYXR0cmlidXRlcy5BbGNvaG9sKSkNCg0KDQpyZXN0X2ZuIDwtIGZ1bmN0aW9uIChkYXRhc2V0LCBkYXRhc2V0MSwgdmFyMSkgew0KdmFyMSA8LSBlbnF1byh2YXIxKSANCnJlc3RfYWxjbyA8LSBkYXRhc2V0ICU+JQ0KZ3JvdXBfYnkoISF2YXIxKSAlPiUNCnN1bW1hcmlzZShuID0gbigpKSAlPiUNCm11dGF0ZSh0b3RhbCA9IHN1bShuKSkgJT4lIA0KbXV0YXRlKHBlcmNlbnQgPSByb3VuZCgobi8gdG90YWwpKjEwMCwgMSkpIA0KDQoNCmdncGxvdChyZXN0X2FsY28sIGFlcyh4ID0gYXR0cmlidXRlcy5BbGNvaG9sLCB5ID0gcGVyY2VudCkgKSArIA0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICdwdXJwbGUnLCB3aWR0aCA9IDAuNikgKyANCiAgbGFicyh4PSdBbGNvaG9sIHNlcnZpY2UnKSArIA0KICBsYWJzKCB5ID0gJ1BlcmNlbnQgb2YgdG90YWwgbnVtYmVyIG9mIHJlc3RhdXJhbnRzJykgKw0KICBsYWJzKHRpdGxlID0gJ0FsY29ob2wgc2VydmljZSBsZXZlbHMgaW4gb3BlcmF0aW5nIHJlc3RhdXJhbnRzJykgKyANCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsgDQogIGdlb21fdGV4dChhZXMobGFiZWw9cGVyY2VudCksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAxKSwNCiAgdmp1c3QgPSAtMC41LCBzaXplID0gNCkgKyBzY2FsZV95X2NvbnRpbnVvdXMobGltID0gYygwLCAxMDApKQ0KfQ0KDQpyZXN0X2ZuKHJlc3RfMSwgcmVzdF9hbGNvLCBhdHRyaWJ1dGVzLkFsY29ob2wpDQoNCmBgYA0KDQpJbiB0ZXJtcyBvZiBhbGNvaG9sIHNlcnZpY2UgbGV2ZWxzIGluIHJlc3RhdXJhbnRzLCB3ZSBmaW5kIHRoYXQgaXRzIGFib3V0IDUwLzUwLiBBcm91bmQgaGFsZiBvZiByZXN0YXVyYW50cyAoNTEuMyUpIHdpbGwgYWN0dWFsbHkgc2VydmUgYWxjb2hvbCBvZiBzb21lIHNvcnQgd2l0aCAxNSUgc2VydmluZyBvbmx5IGJlZXIgYW5kIHdpbmUgd2hpbGUgb3ZlciAzNSUgd2lsbCBoYXZlIGEgZnVsbCBiYXIuIA0KT2YgY291cnNlLCBoYXZpbmcgYWxjb2hvbCBpbiBhIHJlc3RhdXJhbnQgaXMgZ3JlYXQsIGJ1dCBkbyBhbGNvaG9sIHNlcnZpY2UgbGV2ZWxzIGRpZmZlciBhbW9uZ3N0IGRpZmZlcmVudCBjYXRlZ29yaWVzIG9mIHJlc3RhdXJhbnRzPyBUaGUgZmFjdG9yIHRoYXQgZGlmZmVyZW50aWF0ZXMgcmVzdGF1cmFudHMgdGhlIG1vc3Qgd291bGQgcHJvYmFibHkgYmUgdGhlIHByaWNlIHJhbmdlLiANCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDcuNX0NCg0KcmVzdF9hbGNvX2FsbCA8LSByZXN0XzElPiUNCmdyb3VwX2J5KGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNQcmljZVJhbmdlMiwgYXR0cmlidXRlcy5BbGNvaG9sKSAlPiUNCnN1bW1hcmlzZShuID0gbigpKSAlPiUNCm11dGF0ZSh0b3RhbCA9IHN1bShuKSkgJT4lIA0KbXV0YXRlKHBlcmNlbnQgPSByb3VuZCgobi8gdG90YWwpKjEwMCwgMSkpIA0KDQpnZ3Bsb3QocmVzdF9hbGNvX2FsbCwgYWVzKHggPSBhdHRyaWJ1dGVzLkFsY29ob2wsIHkgPSBwZXJjZW50KSkgKyANCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAncHVycGxlJywgd2lkdGggPSAwLjYpICsgDQogIGxhYnMoeD0nQWxjb2hvbCBzZXJ2aWNlJykgKw0KICBsYWJzKHkgPSAnUGVyY2VudCBvZiB0b3RhbCBudW1iZXIgb2YgcmVzdGF1cmFudHMnKSArDQogIGxhYnModGl0bGUgPSAnQWxjb2hvbCBzZXJ2aWNlIGxldmVscyBpbiByZXN0YXVyYW50cyBhY3Jvc3MgcHJpY2UgcmFuZ2VzJykgKyANCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsgDQogIGdlb21fdGV4dChhZXMobGFiZWw9cGVyY2VudCksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAxKSwNCiAgdmp1c3QgPSAtMC41LCBzaXplID0gNCkgKyBzY2FsZV95X2NvbnRpbnVvdXMobGltID0gYygwLCAxMDApKSArIA0KICBmYWNldF9ncmlkKC4gfiBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIpICsgDQogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gYygiYmVlciAmIHdpbmUgICAgIiwgIiAgIGZ1bGwgYmFyIiwgIm5vbmUiKSkgDQoNCmBgYA0KDQpBbGNvaG9sIGlzIGdlbmVyYWxseSBub3Qgc2VydmVkIGluIHRoZSBsZWFzdCBleHBlbnNpdmUgcmVzdGF1cmFudHMsIHdoaWxlIHRob3NlIGluIHRoZSBwcmljZSBjYXRlZ29yeSAyIChhdmVyYWdlKSBvZmZlciBhbGNvaG9sIHNlcnZpY2UgYXQgYXJvdW5kIGEgNzUlIHJhdGUsIGFuZCB0aG9zZSBpbiBpbiB0aGUgbW9zdCBleHBlbnNpdmUgcmVzdGF1cmFudHMgYWxtb3N0IGFsbCBzZXJ2ZSBhbGNvaG9sLiBJdCBpcyBhIGJpdCBzdXJwaXNpbmcsIGhvd2V2ZXIsIHRoYXQgdGhlIHBlcmNlbnRhZ2Ugb2YgdGhvc2UgdGhhdCBvZmZlciBmdWxsIGJhciBkZWNsaW5lcyBzbGlnaHRseSBpbiB0aGUgaGlnaGVzdCBwcmljZSByYW5nZSBvZiByZXN0YXVyYW50cy4NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDcuNX0NCg0KI1NpbWlsYXIgdG8gcmVzdF8wIGFuZCByZXN0XzEsIGV4Y2VwdCB0aGF0IGRhdGFzZXQgb25seSBlbnN1cmVzIHRoYXQgbm9pc2UgbGV2ZWwgZGF0YSBpcyBub3QgTkEgDQpyZXN0XzIgPC0gc3Vic2V0KHllbHBfZmxhdDEsICFpcy5uYShhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIpICYgDQogIGlzX29wZW4gPT0gMSAmDQogICFpcy5uYShhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzVGFrZU91dCkgJiANCiAgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNEZWxpdmVyeSkgJiANCiAgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNUYWJsZVNlcnZpY2UpICYgDQogICFpcy5uYShhdHRyaWJ1dGVzLk5vaXNlTGV2ZWwpKQ0KDQoNCnJlc3Rfbm9pc2UgPC0gcmVzdF8yICU+JQ0KZ3JvdXBfYnkoYXR0cmlidXRlcy5Ob2lzZUxldmVsKSAlPiUNCnN1bW1hcmlzZShuID0gbigpKSAlPiUNCm11dGF0ZSh0b3RhbCA9IHN1bShuKSkgJT4lIA0KbXV0YXRlKHBlcmNlbnQgPSByb3VuZCgobi8gdG90YWwpKjEwMCwgMSkpIA0KDQpnZ3Bsb3QocmVzdF9ub2lzZSwgYWVzKHggPSBhdHRyaWJ1dGVzLk5vaXNlTGV2ZWwsIHkgPSBwZXJjZW50KSkgKyANCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAnZ3JleScsIHdpZHRoID0gMC42KSArIA0KICBsYWJzKHg9J05vaXNlIGxldmVsJykgK2xhYnMoIHkgPSAnUGVyY2VudCBvZiB0b3RhbCBudW1iZXIgb2YgcmVzdGF1cmFudHMnKSArIA0KICBsYWJzKHRpdGxlID0gJ05vaXNlIGxldmVscyBpbiBvcGVyYXRpbmcgcmVzdGF1cmFudHMnKSArIA0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKyANCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbSA9IGMoMCwgMTAwKSkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsPXBlcmNlbnQpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMSksDQogIHZqdXN0ID0gLTAuNSwgc2l6ZSA9IDQpDQpgYGANCg0KT2YgY291cnNlLCBhbiBpbnRyb2R1Y3RvcnkgZXhwbG9yYXRvcnkgYW5hbHlzaXMgb2YgWWVscC1yYXRlZCByZXN0YXVyYW50cyB3b3VsZCBub3QgYmUgY29tcGxldGUgd2l0aG91dCBhdCBsZWFzdCBrbm93aW5nIHNvbWUgaW5mb3JtYXRpb24gb24gdGhlIG5vaXNlIGxldmVscyBvZiB0aGUgcmVzdGF1cmFudC4gTW9zdCByZXN0YXVyYW50cywgYWJvdXQgdHdvLXRoaXJkcywgaGFkIGF2ZXJhZ2Ugbm9pc2UgbGV2ZWxzLCB3aGlsZSBvdmVyIDIwJSBhcmUgcXVpZXQuIE9ubHkgYSBzbWFsbCBtaW5vcml0eSAoYXJvdW5kIDEwJSkgb2YgcmVzdGF1cmFudHMgYXJlIGNsYXNzaWZpZWQgYXMgYmVpbmcgaW4gdGhlIGxvdWQgb3IgdmVyeSBsb3VkIHJhbmdlLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoID0gNy41fQ0KDQojUGFyc2UgZGF0YSB0byBvYnRhaW4gcmV2aWV3X2NvdW50IGJ5IGNpdHkgb3Igc3RhdGUNCg0Kbl9yZXZpZXdzMSA8LSB5ZWxwX2ZsYXQxICU+JQ0KZ3JvdXBfYnkoc3RhdGUsIHJldmlld19jb3VudCkgJT4lDQpzdW1tYXJpc2UodG90YWxfc3VtID0gc3VtKHJldmlld19jb3VudCkpJT4lDQphcnJhbmdlKGRlc2MocmV2aWV3X2NvdW50KSkgJT4lDQpzdW1tYXJpc2UodG90YWxfcmV2aWV3cyA9IHN1bSh0b3RhbF9zdW0pKSAlPiUNCmFycmFuZ2UoZGVzYyh0b3RhbF9yZXZpZXdzKSkNCg0KI1Bsb3QgdGhlIG51bWJlciBvZiByZXZpZXdzIGJ5IHN0YXRlIChsaW1pdCB0byB0b3AgMTAgc3RhdGVzKQ0KZ2dwbG90KG5fcmV2aWV3czEsIGFlcyhyZW9yZGVyKHN0YXRlLCAtdG90YWxfcmV2aWV3cyksIHRvdGFsX3Jldmlld3MpKSArIA0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICdkYXJrYmx1ZScpICsgbGFicyh4PSdzdGF0ZScpICsgIA0KICBsYWJzKHg9J3N0YXRlJykgK2xhYnMoIHkgPSAnTnVtYmVyIG9mIHJldmlld3MnKSArDQogIGxhYnModGl0bGUgPSAnRGlzdHJpYnV0aW9uIG9mIHJldmlldyBjb3VudCBhY3Jvc3Mgc3RhdGVzJykgKyANCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpDQoNCmBgYA0KDQojIFVuaXZhcmlhdGUgQW5hbHlzaXMNCg0KIyMjIFdoYXQgaXMgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YSBzZXQ/DQpUaGVyZSBhcmUgMTU2NjM5IGRhdGEgcG9pbnRzIGluIHRoZSBZZWxwIGFjYWRlbWljIGRhdGEgc2V0LCBhbmQgaW5jbHVkZXMgWWVscC1yYXRlZCBlc3RhYmxpc2htZW50cyBhY3Jvc3MgYSB2YXJpZXR5IG9mIGRpZmZlcmVudCBnZW9ncmFwaGllcyB0aGF0IGFyZSBtYWlubHkgYmFzZWQgaW4gTm9ydGggQW1lcmljYS4NClRoZXJlIGFyZSAxMDEgdmFyaWFibGVzIGluIHRoZSBkYXRhIHNldCBhbmQgb25seSBhIGZldyBvZiB0aGVtIHdlcmUgYW5hbHl6ZWQgaW4gbXkgdW5pdmFyaWF0ZSBhbmFseXNpcy4NCkluIHRoZSB1bml2YXJpYXRlIGFuYWx5c2lzLCB0aGVzZSBpbmNsdWRlIHRoZSBub2lzZSBsZXZlbCwgYWxjb2hvbCBzZXJ2aWNlLCBwcmljZSByYW5nZSwgc3RhcnMsIGFuZCByZXZpZXcgY291bnQuDQoNCkFzaWRlIGZyb20gcmV2aWV3X2NvdW50IHdoaWNoIGlzIGFuIGludGVnZXIgdmFyaWFibGUsIGFsbCBvdGhlciB2YXJpYWJsZXMgZm9sbG93IGFyZSBjYXRlZ29yaWNhbCBpbiBuYXR1cmU6DQoNCnN0YXJzIDwtIDEsIDEuNSwgMiwgMi41LCAzLCAzLjUsIDQsIDQuNSwgNSAgIA0KcHJpY2UgcmFuZ2UgPC0gMSwgMiwgMywgNCAgICANCmFsY29ob2wgc2VydmljZSA8LSBub25lLCBiZWVyX2FuZF93aW5lLCBmdWxsX2JhciAgIA0Kbm9pc2UgbGV2ZWwgPC0gcXVpZXQsIGF2ZXJhZ2UsIGxvdWQsIHZlcnlfbG91ZCAgICANCmF0dGlyZSA8LSBjYXN1YWwsIGZvcm1hbCwgZHJlc3N5DQoNClRoZSBiaW5hcnkgKHllcy9ubykgdmFyaWFibGVzIGV4YW1pbmVkIGFyZTogDQppcyBvcGVuLCBkZWxpdmVyeSwgdGFrZW91dCwgZ29vZCBmb3IgZGlubmVyLCB0YWJsZSBzZXJ2aWNlDQoNCkdlb2dyYXBoaWNhbCBpbmZvcm1hdGlvbiBzdWNoIGFzIGxvbmdpdHVkZSBpcyBleHByZXNzZWQgYmV0d2VlbiAtMTgwIGFuZCAxODAgZGVncmVlcywgd2hpbGUgbGF0aXR1ZGUgaXMgZXhwcmVzc2VkIGJldHdlZW4gLTkwIGFuZCA5MCBkZWdyZWVzLg0KDQoNCiMjIyBJbnRlcmVzdGluZyBvYnNlcnZhdGlvbnM6IA0KMSkgQXZlcmFnZSBudW1iZXIgb2YgcmV2aWV3cyBwZXIgZXN0YWJsaXNobWVudCBpcyBhcm91bmQgMzANCjIpIENsb3NlIHRvIGhhbGYgb2YgcmF0aW5ncyBhcmUgaW4gdGhlIDMuNSB0byA0IHN0YXJzIHJhbmdlDQozKSBBbGNvaG9sIHNlcnZpY2UgaXMgcHJvdmlkZWQgaW4gb3ZlciA1MCUgb2YgcmVzdGF1cmFudHMNCjQpIEFsbW9zdCBhbGwgcmVzdGF1cmFudHMgYXJlIGluIHRoZSAxLTIgcHJpY2UgcmFuZ2UgKGluZXhwZW5zaXZlIHRvIGF2ZXJhZ2UpDQo1KSBNb3N0IHJlc3RhdXJhbnRzIGhhdmUgcXVpZXQgdG8gYXZlcmFnZSBub2lzZSBsZXZlbHMNCjYpIFRoZSBzYW1wbGUgb2YgZXN0YWJsaXNobWVudHMgcHJvdmlkZWQgaW4gdGhlIGRhdGEgc2V0IGFyZSBtb3N0bHkgaW4gQXJpem9uYSwgTmV2YWRhIGFuZCBPbnRhcmlvDQoNCg0KIyMjIFdoYXQgaXMvYXJlIHRoZSBtYWluIGZlYXR1cmUocykgb2YgaW50ZXJlc3QgaW4geW91ciBkYXRhc2V0Pw0KVGhlIG1haW4gZmVhdHVyZXMgb2YgaW50ZXJlc3QgaW4gdGhpcyBkYXRhIHNldCBhcmUgcmV2aWV3IGNvdW50LCBwcmljZSByYW5nZSBhbmQgc3RhcnMuDQoNCg0KIyMjIFdoYXQgb3RoZXIgZmVhdHVyZXMgaW4gdGhlIGRhdGFzZXQgZG8geW91IHRoaW5rIHdpbGwgaGVscCBzdXBwb3J0IHlvdXIgaW52ZXN0aWdhdGlvbiBpbnRvIHlvdXIgZmVhdHVyZShzKSBvZiBpbnRlcmVzdD8NCg0KQWxjb2hvbCBzZXJ2b2NlLCBub2lzZSBsZXZlbCwgZ2VvZ3JhcGhpY2FsIGZlYXR1cmVzIHN1Y2ggYXMgbG9uZ2l0dWRlIGFuZCBsYXRpdHVkZSBhbG9uZyB3aXRoIHN0YXRlLCBpc19vcGVuLCBhcyB3ZWxsIGFzIG51bWVyb3VzIHJlc3RhdXJhbnQgYXR0cmlidXRlcyBzdWNoIGFzIHRhYmxlIHNlcnZpY2UsIGRlbGl2ZXJ5LCB0YWtlb3V0LCBhdHRpcmUsIGlmIGl0cyBnb29kIGZvciBsdW5jaCwgZGlubmVyLCBkZXNzZXJ0IGV0Yy4gd291bGQgYmUgZ29vZCBmZWF0dXJlcyB0aGF0IHdvdWxkIGNvbXBsZW1lbnQgdGhlIGFuYWx5c2lzIG9uIHN0YXJzLCBwcmljZSByYW5nZSBhbmQgcmV2aWV3IGNvdW50Lg0KDQoNCiMjIyBEaWQgeW91IGNyZWF0ZSBhbnkgbmV3IHZhcmlhYmxlcyBmcm9tIGV4aXN0aW5nIHZhcmlhYmxlcyBpbiB0aGUgZGF0YXNldD8NCg0KQSBuZXcgdmFyaWFibGUgY2FsbGVkIGZ1bGxfc2VydmljZSB3YXMgY3JlYXRlZCBmb3IgdGhlIHB1cnBvc2VzIG9mIG15IGFuYWx5c2lzIChsYXRlciB1c2VkIGluIHRoZSBiaXZhcmlhdGUgYW5hbHlzaXMgc2VjdGlvbiksICB3aGljaCBpcyBhIGNhdGVnb3JpY2FsIHZhcmlhYmxlIHRoYXQgY29tYmluZXMgdGFibGUgc2VydmljZSwgZGVsaXZlcnkgYW5kIHRha2VvdXQgc2VydmljZXMgYWxsIGJlaW5nIG9mZmVyZWQgb3Igbm90LiBJdHMgdmFsdWUgaXMgMSB3aGVuIHRhYmxlIHNlcnZpY2UsIGRlbGl2ZXJ5IGFuZCB0YWtlb3V0IHNlcnZpY2VzIGFyZSBwcm92aWRlZCBhdCB0aGUgcmVzdGF1cmFudCwgYW5kIDAgaWYgZXZlbiBvbmUgb2YgdGhlc2Ugc2VydmljZXMgaXMgbm90IG9mZmVyZWQuIFRoZSByYXRpb25hbGUgYmVoaW5kIGNyZWF0aW5nIHRoaXMgdmFyaWFibGUgd2FzIHRvIHNlZSB0aGUgcGVyY2VudGFnZSBvZiByZXN0YXVyYW50cyB0aGF0IHdlcmUgYWJsZSB0byByZXNwb25kIHRvIGFsbCBzb3J0cyBvZiBkaW5pbmcgb3B0aW9ucy4gVGhlcmUgd2VyZSBvdGhlciB2YXJpYWJsZXMgc3VjaCBhcyBjYXRlcmluZywgYnV0IGl0IHdhcyBub3QgaW5jbHVkZWQgYXMgaXQgbWF5IGhhdmUgYmVlbiB0b28gcmVzdHJpY3RpdmUuDQoNCkkgYWxzbyBjcmVhdGVkIGEgbmV3IHZhcmlhYmxlIGNhbGxlZCAidmFsdWUiIHdoaWNoIGlzIGRlZmluZWQgYXMgWWVscCBzdGFycyBkaXZpZGVkIGJ5IHByaWNlIHJhbmdlLCB3aGljaCBtZWFzdXJlcyB0aGUgYW1vdW50IG9mIHZhbHVlIHRoYXQgeW91IG9idGFpbiBpbiB0ZXJtcyBvZiBhbiBleHBlcmllbmNlIGF0IGFuIGVzdGFibGlzaG1lbnQgdGhhdCBmb3IgZWFjaCBkb2xsYXIgdGhhdCB5b3Ugc3BlbmQuIEEgbG93ZXIgcHJpY2UgcmFuZ2UgYW5kIGEgaGlnaGVyIFllbHAgc3RhciByYXRpbmcgbWVhbnMgYSBoaWdoZXIgdmFsdWUsIHdoaWxlIGNvbnZlcnNlbHksIGEgaGlnaGVyIHByaWNlIHJhbmdlIGFuZCBsb3dlciBZZWxwIHN0YXIgcmF0aW5nIGVxdWF0ZXMgYSBsb3dlciB2YWx1ZS4NCg0KDQojIyMgT2YgdGhlIGZlYXR1cmVzIHlvdSBpbnZlc3RpZ2F0ZWQsIHdlcmUgdGhlcmUgYW55IHVudXN1YWwgZGlzdHJpYnV0aW9ucz8gRGlkIHlvdSBwZXJmb3JtIGFueSBvcGVyYXRpb25zIG9uIHRoZSBkYXRhIHRvIHRpZHksIGFkanVzdCwgb3IgY2hhbmdlIHRoZSBmb3JtIG9mIHRoZSBkYXRhPyBJZiBzbywgd2h5IGRpZCB5b3UgZG8gdGhpcz8NCg0KVGhlcmUgd2VyZSBtYW55IGNhc2VzIHdoZXJlIG51bGwgdmFsdWVzIGV4aXN0ZWQgZm9yIHRoZSByZXN0YXVyYW50IHZhcmlhYmxlcyBhbmQgc28gdGhlc2UgdmFsdWVzIHdlcmUgbm90IGluY2x1ZGVkIGluIG9yZGVyIHRvIGdldCBhbiBhcHByb3hpbWF0aW9uIG9mIHdoYXQgd2FzIG9ubHkgY29uc2lkZXJlZCB0byBiZSBhIHJlc3RhdXJhbnQuIFRoaXMgcHJldmVudHMgaW5jbHVkaW5nIHN1cGVybWFya2V0cyBvciBtZWRpY2FsIGNsaW5pY3Mgb3IgZXZlbiBhbXVzZW1lbnQgcGFya3MgdGhhdCBtaWdodCBoYXZlIHNvbWUgZm9vZCBzZXJ2aWNlcyBhdmFpbGFibGUgYnV0IGFyZSBub3QgcmVzdGF1cmFudHMgb24gaXRzIG93bi4gQWxzbywgdGhlIGRhdGEgaGFzIGFsc28gYmVlbiBzdWJzZXR0ZWQgdG8gb25seSBhY2NvdW50IGZvciB2YWx1ZXMgaW4gY2VydGFpbiBzdGF0ZXMgdGhhdCB3ZXJlIG9wZXJhdGluZyBkZXBlbmRpbmcgb24gdGhlIGFuYWx5c2lzLiBVcG9uIGV4YW1pbmluZyB0aGUgdW5pdmFyaWF0ZSBwbG90cywgSSBkaWQgbm90IGV4YW1pbmUgYW55IHVudXN1YWwgZGlzdHJpYnV0aW9ucy4NCg0KDQoNCiMgQml2YXJpYXRlIFBsb3RzIFNlY3Rpb24NCg0KVGhlIG51bWJlciBvZiByZXZpZXdzIChyZXZpZXdfY291bnQpIGlzIGEgdmVyeSBpbXBvcnRhbnQgdmFyaWFibGUgaW4gdGhlIFllbHAgZGF0YSBzZXQuIEluIGZhY3QsIGl0IGlzIHRoZSBvbmx5IHZhcmlhYmxlIHRoYXQgaXMgbm90IGRpc2NyZXRlIG9yIGNhdGVnb3JpY2FsIG90aGVyIHRoYW4gbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZSwgYW5kIGNhbiBiZSBhbmFseXplZCBhbG9uZyBhIHZhcmlldHkgb2YgZGlmZmVyZW50IGNhdGVnb3JpY2FsIHZhcmlhYmxlcy4gDQoNCkFzIGl0IGFwcGVhcnMsIHRoZSByZXZpZXcgY291bnQgbnVtYmVycyBzZWVtIHVuZG91YnRlZGx5IGJpYXNlZCB0b3dhcmRzIE5ldmFkYSBhbmQgQXJpem9uYSBhcyBzaG93biBmcm9tIHRoZSBwbG90IGJlbG93LiBUaGlzIHNvcnQgb2YgbWFrZXMgc2Vuc2UgYXMgd2Ugc2F3IGVhcmxpZXIgdGhhdCB0aGUgbnVtYmVyIG9mIGVzdGFibGlzaG1lbnRzIHdlcmUgYWxzbyBzb21ld2hhdCBiaWFzZWQgdG93YXJkcyBOZXZhZGEsIEFyaXpvbmEgYW5kIE9udGFyaW8uIFdoYXQgaXMgb2RkIGlzIHRoYXQgZXZlbiB0aG91Z2ggTlYgYW5kIE9OIGhhZCBhIHNpbWlsYXIgbnVtYmVyIG9mIGVzdGFibGlzaG1lbnRzIGluIHRoaXMgZGF0YXNldCwgdGhlIG51bWJlciBvZiByZXZpZXdzIGlzIHN1YnN0YW50aWFsbHkgaGlnaGVyIGZvciBOViB0aGFuIGl0IGlzIGZvciBPTi4NCg0KT25lIG9mIHRoZSB0aGluZ3MgdGhhdCBJIG5vdyB3YW50IHRvIGxvb2sgYXQgaXMgdGhlIGRpc3RyaWJ1dGlvbiBvZiByZXZpZXdfY291bnQgYnkgZXN0YWJsaXNobWVudCwgYW5kIHRvIGNvbXB1dGUgdGhlIG1lYW5zIGFjcm9zcyBlYWNoIG9mIHRoZSBzdGF0ZXMgc2hvd24gYWJvdmUuIA0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQpuX3Jldmlld3MyIDwtIGhlYWQobl9yZXZpZXdzMSwgbj0xMCkNCm5fcmV2aWV3czINCg0KYGBgDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGggPSA3LjV9DQoNCmdncGxvdCh5ZWxwX2ZsYXQxLCBhZXMoeCA9IHN0YXRlLCB5ID0gcmV2aWV3X2NvdW50KSkgKyBnZW9tX2JveHBsb3QoKSArIA0KICBsYWJzKHRpdGxlID0gIkRpc3BlcnNpb24gb2YgcmV2aWV3IGNvdW50IGFjcm9zcyBzdGF0ZXMiKSArIA0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKyANCiAgbGFicyggeSA9ICdOdW1iZXIgb2YgcmV2aWV3cycpDQoNCmBgYA0KDQpBdCBmaXJzdCBnbGFuY2UsIGl0IHNlZW1zIHRoYXQgYXJlIGNlcnRhaW5seSBhIGxhcmdlIG51bWJlciBvZiBlc3RhYmxpc2htZW50cyBpbiBOZXZhZGEgdGhhdCBoYXZlIGFuIGV4dHJlbWVseSBoaWdoIHJldmlldyBjb3VudCwgdGhvdWdoIHRoZSBtZWFuIG51bWJlciBvZiByZXZpZXdzIHBlciBlc3RhYmxpc2htZW50IGlzIGFjdHVhbGx5IG9ubHkgYXJvdW5kIDMwIGFjcm9zcyB0aGUgZW50aXJlIGRhdGEgc2V0Lg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoID0gNy41fQ0KZ2dwbG90KHllbHBfZmxhdDEsIGFlcyh4ID0gc3RhdGUsIHkgPSByZXZpZXdfY291bnQpKSArIGdlb21fYm94cGxvdCgpICsgDQogIGxhYnModGl0bGUgPSAiRGlzcGVyc2lvbiBvZiByZXZpZXcgY291bnRzIGFjcm9zcyBzdGF0ZXMiKSArIA0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKyANCiAgbGFicyggeSA9ICdOdW1iZXIgb2YgcmV2aWV3cycpICsgY29vcmRfY2FydGVzaWFuKHlsaW09YygwLCA3MCkpDQpgYGANCg0KWm9vbWluZyBjbG9zZXIgaW50byB0aGUgYm94IHBsb3QsIHdlIHNlZSB0aGF0IG1lZGlhbiBhY3Jvc3MgYWxsIHN0YXRlcyBpcyBzb21ld2hlcmUgYmV0d2VlbiA3IHRvIDEyIHJldmlld3MsIHdoaWNoIG1lYW5zIHRoYXQgYSBzaXphYmxlIHByb3BvcnRpb24gb2YgWWVscC1yYXRlZCBlc3RhYmxpc2htZW50cyBoYXZlIGZldyB0byBubyByYXRpbmdzLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQphdmdfc3RhdGVfcmV2aWV3cyA8LSB5ZWxwX2ZsYXQxJT4lDQpncm91cF9ieShzdGF0ZSklPiUNCnN1bW1hcmlzZShyZXZpZXdfY291bnRfbWVhbiA9IG1lYW4ocmV2aWV3X2NvdW50KSkgJT4lDQphcnJhbmdlKGRlc2MocmV2aWV3X2NvdW50X21lYW4pKQ0KYXZnX3N0YXRlX3Jldmlld3MgDQoNCg0KYGBgDQoNCkR1ZSB0byB0aGUgbGFyZ2UgbnVtYmVyIG9mIGVzdGFibGlzaG1lbnRzIHRoYXQgaGF2ZSBhIHJldmlldyBjb3VudCBpbiB0aGUgdGhvdXNhbmRzLCB0aGlzIHNrZXdzIHRoZSBtZWFuIHVwd2FyZCBjb25zaWRlcmFibHkgc3VjaCB0aGF0IHRoZSBtZWFuIGVuZHMgdXAgYmVpbmcgZG91YmxlIHRvIHF1YWRydXBsZSB0aGUgbWVkaWFuIGZvciBlYWNoIHN0YXRlLg0KDQpXaGVuIGNvbXBhcmVkIGFjcm9zcyBzdGF0ZXMsIGl0IHR1cm5zIG91dCB0aGF0IHRoZSBhdmVyYWdlIGFjcm9zcyBlYWNoIHN0YXRlIGluIHRlcm1zIG9mIHRoZSByZXZpZXcgY291bnQgcGVyIGVzdGFibGlzaG1lbnQgaXMgYWN0dWFsbHkgcXVpdGUgZGlmZmVyZW50IHdpdGggTmV2YWRhIGhhdmluZyBhIHN1YnN0YW50aWFsbHkgaGlnaGVyIHJldmlldyBjb3VudCB0aGFuIG90aGVyIHN0YXRlcy4gVGhpcyBleHBsYWlucyB3aHkgZXZlbiB0aG91Z2ggdGhlIG51bWJlciBvZiBZZWxwLXJhdGVkIGVzdGFibGlzaG1lbnRzIGluIE9udGFyaW8gYW5kIE5ldmFkYSBhcmUgcm91Z2hseSBlcXVhbCwgdGhlIHJldmlld19jb3VudCB2YXJpYWJsZSB3YXMgc28gbXVjaCBoaWdoZXIgZm9yIE5ldmFkYSB0aGFuIGZvciBPbnRhcmlvLg0KDQoNCk5vdywgbW92aW5nIG9uIGZyb20gdGhlIHJldmlldyBjb3VudCwgd2hhdCBhYm91dCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gcHJpY2UgcmFuZ2UgYW5kIHN0YXJzIGZvciByZXN0YXVyYW50cz8NCg0KQW5kIGhvdyBkb2VzIHRoaXMgdmFyeSB3aXRoIG5vaXNlIGxldmVscz8NCkRvIG1vcmUgZXhwZW5zaXZlIHBsYWNlcyB0aGF0IGFyZSBxdWlldGVyIGhhdmUgaGlnaGVyIHJhdGluZ3M/DQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGggPSA3LjV9DQoNCg0KI0NvZGUgZ3JvdXBzIGJ5IG5vaXNlIGxldmVscyBiYXNlZCBvbiBhdmVyYWdlIFllbHAgc3RhcnMsIHRoaXMgYWxsb3dzIHVzIHRvIGFuYWx5emUgaG93IGF2ZXJhZ2UgcmF0aW5ncyBjaGFuZ2UgYXMgbm9pc2UgbGV2ZWxzIGluY3JlYXNlDQoNCnJlc3Rfbm9pc2UgPC0gcmVzdF8yICU+JQ0KZ3JvdXBfYnkoYXR0cmlidXRlcy5Ob2lzZUxldmVsKSAlPiUNCnN1bW1hcmlzZShuPW1lYW4oc3RhcnMpKQ0KDQojTmV3IGZhY3RvcnMgd3JpdHRlbiBpbiBzbyB0aGF0IHBsb3QgY2FuIGJlIGNyZWF0ZWQgZnJvbSBsb3dlc3QgdG8gdGhlIGxvdWRlc3QgbGV2ZWwgb2Ygbm9pc2UNCnJlc3Rfbm9pc2UkYXR0cmlidXRlcy5Ob2lzZUxldmVsIDwtIGZhY3RvcihyZXN0X25vaXNlJGF0dHJpYnV0ZXMuTm9pc2VMZXZlbCwgDQogIGxldmVscz1jKCJxdWlldCIsICJhdmVyYWdlIiwgImxvdWQiLCAidmVyeV9sb3VkIikpDQoNCiNEZWNpZGVkIG5vdCB0byB1c2UgbGluZSBwbG90IGR1ZSB0byByZXZpZXcgc3VnZ2VzdGlvbnMNCiNnZ3Bsb3QoYWVzKHggPSBhdHRyaWJ1dGVzLk5vaXNlTGV2ZWwsIHkgPSBuLCBncm91cCA9IDEpLCBkYXRhID0gcmVzdF9ub2lzZSkgKyANCiMgIGdlb21fbGluZShzaXplID0gMikgKyBnZW9tX3BvaW50KHNpemUgPSA0LCBjb2xvdXIgPSAiZGFya2JsdWUiKSArIA0KIyAgbGFicyh0aXRsZSA9ICJSZWxhdGlvbnNoaXAgYmV0d2VlbiBub2lzZSBsZXZlbCBhbmQgcmF0aW5ncyBpbiByZXN0YXVyYW50cyIpICsgDQojICBsYWJzKHggPSAiTm9pc2UgbGV2ZWwiKSArIGxhYnMoeT0gIlJhdGluZyAoaW4gc3RhcnMpIikgKyANCiMgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSAgDQoNCiNVc2UgbG9sbGlwb3AgcGxvdCBpbnN0ZWFkIG9mIGxpbmUgY2hhcnQgdG8gc2hvdyBkZWNsaW5lIGluIHJhdGluZ3MgYWNyb3NzIG5vaXNlIGxldmVscy4NCiNVc2VkIGxvbGxpcG9wIHBsb3QgaW5zdGVhZCBvZiBiYXIgcGxvdCwgYmVjYXVzZSBpdCBiZXR0ZXIgc2hvd3MgcmVsYXRpb25zaGlwIGFjcm9zcyBub2lzZSBsZXZlbHMgdGhhbiBiYXIgcGxvdA0KI0Fsc28gaW5jcmVhc2VzIHZhcmlldHkgb2YgdmlzdWFsaXphdGlvbnMgYmVpbmcgdXNlZA0KZ2dwbG90KHJlc3Rfbm9pc2UsIGFlcyh4ID0gYXR0cmlidXRlcy5Ob2lzZUxldmVsLCB5ID0gbikpICsgDQogIGdlb21fcG9pbnQoc2l6ZT04LCBjb2xvdXIgPSAiI2ZlYzQ0ZiIpICsgDQogIGdlb21fc2VnbWVudChhZXMoeCA9IGF0dHJpYnV0ZXMuTm9pc2VMZXZlbCAsIA0KICAgICAgICAgICAgICAgICAgIHhlbmQgPSBhdHRyaWJ1dGVzLk5vaXNlTGV2ZWwsIA0KICAgICAgICAgICAgICAgICAgIHk9MCwgDQogICAgICAgICAgICAgICAgICAgeWVuZD0gbiksIGNvbG91ciA9ICIjZTY1NTBkIikgKw0KICBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKDIuNSwgNCkpICsNCiAgbGFicyh0aXRsZSA9ICJSZWxhdGlvbnNoaXAgYmV0d2VlbiBub2lzZSBsZXZlbCBhbmQgWWVscCBzdGFycyBpbiByZXN0YXVyYW50cyIpICsgDQogIGxhYnMoeCA9ICJOb2lzZSBsZXZlbCIpICsgbGFicyh5PSAiUmF0aW5nIChpbiBzdGFycykiKSArIA0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgDQoNCmBgYA0KDQpFYXJsaWVyIGluIHRoZSB1bml2aWFyYXRlIGFuYWx5c2lzIHNlY3Rpb24sIHdlIGZvdW5kIHRoYXQgbW9zdCByZXN0YXVyYW50cyB3ZXJlIG9mIGF2ZXJhZ2UgYW5kIHF1aWV0IG5vaXNlIGxldmVscy4NCkJ1dCB3aHkgbWlnaHQgdGhpcyBiZSB0aGUgY2FzZT8gVGhlIGxpbmUgcGxvdCBiZWxvdyBzaG93cyB0aGF0IHRoZXJlIGNlcnRhaW5seSBpcyBhIHJhdGluZ3MgcHJlbWl1bSB0byBoYXZpbmcgYSBxdWlldCByZXN0YXVyYW50IGFzIHJlc3RhdXJhbnRzIHRoYXQgd2VyZSBxdWlldGVyIGhhZCBoaWdoZXIgYXZlcmFnZSByYXRpbmdzIGluIGdlbmVyYWwuIEZvciBleGFtcGxlLCBxdWlldCByZXN0YXVyYW50cyBoYWQgYWJvdmUgMy42IGF2ZXJhZ2UgcmF0aW5nLCB3aGlsZSB2ZXJ5IGxvdWQgcmVzdGF1cmFudHMgaGFkIGxlc3MgdGhhbiAzLjAgYXZlcmFnZSByYXRpbmcuDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCg0Kbm9pc2Vfc3RhcnMgPC0gbG0oc3RhcnMgfiBhdHRyaWJ1dGVzLk5vaXNlTGV2ZWwsIGRhdGEgPSBzdWJzZXQocmVzdF8yKSkNCg0Kc3VtbWFyeShub2lzZV9zdGFycykNCg0KYGBgDQoNCkFsdGhvdWdoIGluY3JlYXNlZCBub2lzZSBsZXZlbHMgYXJlIGNvcnJlbGF0ZWQgd2l0aCBkZWNyZWFzZWQgWWVscCBzdGFycyBmb3IgYSByZXN0YXVyYW50LCB0aGUgZGVncmVlIG9mIHZhcmlhbmNlIGV4cGxhaW5lZCBmcm9tIHRoZSBSLXNxdWFyZWQgaXMgb25seSBhYm91dCAzJSwgbWVhbmluZyB0aGF0IG5vaXNlIGxldmVscyBvbmx5IGV4cGxhaW4gYSB2ZXJ5IHNtYWxsIHByb3BvcnRpb24gb2YgdGhlIHJhdGluZ3MgZ2l2ZW4gdG8gYSByZXN0YXVyYW50LiBUaGVyZSBhcmUgbW9zdCBjZXJ0YWlubHkgb3RoZXIgZmFjdG9ycyB0aGF0IHdvdWxkIG1vc3QgbGlrZWx5IGluZmx1ZW5jZSB0aGUgbnVtYmVyIG9mIHN0YXJzIGdpdmVuLg0KDQpCdXQgd2hhdCBlbHNlIG1pZ2h0IGFsc28gaW1wYWN0IHRoZSBudW1iZXIgb2Ygc3RhcnMgdGhhdCBhIFllbHAtcmF0ZWQgcmVzdGF1cmFudCwgY291bGQgcHJpY2UgcmFuZ2UgYmUgb25lIG9mIHRoZW0/DQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGggPSA3LjV9DQoNCiNBZ2FpbiwgZ3JvdXAgYnkgcHJpY2UgcmFuZ2UgYW5kIGNhbGN1bGF0ZSBhdmVyYWdlIG51bWJlciBvZiBzdGFycw0KcmVzdF9zdGFyX3ByaWNlIDwtIHJlc3RfMiAlPiUNCmdyb3VwX2J5KGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNQcmljZVJhbmdlMikgJT4lDQpzdW1tYXJpc2UobiA9IG1lYW4oc3RhcnMpKQ0KDQojTGluZSBwbG90IG5vdCB1c2VkIGFzIHBlciByZXZpZXdlcidzIHN1Z2dlc3Rpb25zDQojZ2dwbG90KGFlcyh4ID0gYXR0cmlidXRlcy5SZXN0YXVyYW50c1ByaWNlUmFuZ2UyLCB5ID0gbiwgZ3JvdXAgPSAxKSwgDQojICBkYXRhID0gcmVzdF9zdGFyX3ByaWNlKSArIGdlb21fbGluZShzaXplID0gMikgKyANCiMgIGdlb21fcG9pbnQoc2l6ZSA9IDQsIGNvbG91ciA9ICJkYXJrYmx1ZSIpICsgDQojICBsYWJzKHRpdGxlID0gIlJlbGF0aW9uc2hpcCBiZXR3ZWVuIHByaWNlIHJhbmdlIGFuZCBZZWxwIHN0YXJzIGluIHJlc3RhdXJhbnRzIikgKyANCiMgIGxhYnMoeCA9ICJQcmljZSBSYW5nZSIpICsgbGFicyh5PSAiUmF0aW5nIChpbiBzdGFycykiKSsgDQojICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgDQoNCg0KZ2dwbG90KHJlc3Rfc3Rhcl9wcmljZSwgYWVzKHggPSBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIsIHkgPSBuKSkgKyANCiAgZ2VvbV9wb2ludChzaXplPTgsIGNvbG91ciA9ICIjNzU2YmIxIikgKyANCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gYXR0cmlidXRlcy5SZXN0YXVyYW50c1ByaWNlUmFuZ2UyICwgDQogICAgICAgICAgICAgICAgICAgeGVuZCA9IGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNQcmljZVJhbmdlMiwgDQogICAgICAgICAgICAgICAgICAgeT0wLCANCiAgICAgICAgICAgICAgICAgICB5ZW5kPSBuKSwgY29sb3VyID0gIiNlNjU1MGQiKSArDQogIGNvb3JkX2NhcnRlc2lhbih5bGltPWMoMi41LCA0KSkgKw0KICBsYWJzKHRpdGxlID0gIlJlbGF0aW9uc2hpcCBiZXR3ZWVuIHByaWNlIHJhbmdlIGFuZCBZZWxwIHN0YXJzIGluIHJlc3RhdXJhbnRzIikgKyANCiAgbGFicyh4ID0gIlByaWNlIFJhbmdlIikgKyBsYWJzKHk9ICJSYXRpbmdzIChpbiBzdGFycykiKSArIA0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgDQoNCmBgYA0KDQpJdCB0dXJucyBvdXQgdGhhdCBhcyB0aGUgcHJpY2UgcmFuZ2UgZm9yIGEgcmVzdGF1cmFudCBpbmNyZWFzZXMsIHRoZSBZZWxwIHN0YXJzIGdpdmVuIGFsc28gdGVuZCB0byBiZSBoaWdoZXIsIHJhbmdpbmcgZnJvbSBhcm91bmQgMy40IHN0YXJzIGF0IGEgcHJpY2UgcmFuZ2Ugb2YgMSBhbmQgYXJvdW5kIDMuNzUgYXQgYSBwcmljZSByYW5nZSBvZiA0LiANCg0KSG93ZXZlciwgZG9pbmcgYSBxdWljayByZWdyZXNzaW9uIHNob3dzIHRoYXQgdGhlIGFtb3VudCBvZiB2YXJpYW5jZSBleHBsYWluZWQgYnkgdGhpcyBtb2RlbCBpcyB2ZXJ5IG11Y2ggaW5zdWZmaWNpZW50IGZvciBleHBsYWluaW5nIGhvdyBtYW55IHN0YXJzIGEgcmVzdGF1cmFudCBnZXRzLiBBbHRob3VnaCB0aGUgcmVzdWx0cyBpbiB0aGUgcmVncmVzc2lvbiBiZWxvdyBzaG93IHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZSwgdGhpcyBpcyBtb3N0IGxpa2VseSBiZWNhdXNlIHRoZXJlIGlzIG9ubHkgb25lIGluZGVwZW5kZW50IHZhcmlhYmxlIChhcyB3YXMgaW4gdGhlIHByZXZpb3VzIGNhc2Ugd2l0aCBub2lzZSBsZXZlbHMpLiANCkluIGFkZGl0aW9uLCB0aGUgYW1vdW50IG9mIHZhcmlhbmNlIGV4cGxhaW5lZCBieSBwcmljZSByYW5nZSBpcyBldmVuIGxlc3MgdGhhbiBmb3Igbm9pc2UgbGV2ZWxzLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQpwcmljZV9zdGFycyA8LSBsbShzdGFycyB+IGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNQcmljZVJhbmdlMiwgDQogIGRhdGEgPSBzdWJzZXQocmVzdF8yKSkNCnN1bW1hcnkocHJpY2Vfc3RhcnMpDQoNCmBgYA0KDQoNCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDcuNX0NCg0KI0NhbGN1bGF0ZSBwZXJjZW50YWdlIG9mIHJlc3RhdXJhbnRzIGJ5IHByaWNlIHJhbmdlDQoNCnJlc3RhdXJhbnRfcHJpY2VfcmFuZ2UgPC0gcmVzdF8wICU+JQ0KZ3JvdXBfYnkoc3RhdGUsIGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNQcmljZVJhbmdlMikgJT4lDQpzdW1tYXJpc2Uobj1uKCkpJT4lDQptdXRhdGUodG90YWwgPSBzdW0obikpICU+JQ0KbXV0YXRlKHBlcmNlbnQgPSByb3VuZCgobi8gdG90YWwpKjEwMCwgMSkpDQoNCmdncGxvdChkYXRhID0gcmVzdGF1cmFudF9wcmljZV9yYW5nZSwgYWVzKHggPSBzdGF0ZSwgeSA9IHBlcmNlbnQsIA0KICBmaWxsPWZhY3RvcihhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIpKSkgKyANCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMC41KSArDQogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZT0iUHJpY2VcblJhbmdlXG4kLSQkJCQiKSArDQogIHNjYWxlX2NvbG91cl9icmV3ZXIoKSArDQogIGxhYnModGl0bGUgPSAiUGVyY2VudGFnZSBvZiByZXN0YXVyYW50cyBieSBwcmljZSByYW5nZSIpKyANCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICANCmBgYA0KDQpMb29raW5nIGF0IHRoZSBwcmljZSByYW5nZSBhZ2Fpbiwgd2UgY2FuIGFsc28gc2VlIHRoYXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiBwcmljZSByYW5nZXMgYWNyb3NzIGRpZmZlcmVudCBnZW9ncmFwaGllcyB2YXJ5IHF1aXRlIGEgYml0LiBJbiB0aGUgcHJvdmluY2Ugb2YgUXVlYmVjLCB0aGVyZSBpcyBhIG11Y2ggaGlnaGVyIHByb3BvcnRpb24gb2YgcmVzdGF1cmFudHMgaW4gdGhlIG1vcmUgZXhwZW5zaXZlIDMtNCBjYXRlZ29yaWVzLCBhbmQgd2l0aCBhIHN1YnN0YW50aWFsbHkgbG93ZXIgcGVyY2VudGFnZSBvZiByZXN0YXVyYW50cyBpbiB0aGUgbGVzcyBleHBlbnNpdmUgcHJpY2UgcmFuZ2UgMS4gDQpUaGlzIGlzIGluIHN0YXJrIGNvbnRyYXN0IHRvIEFaIChBcml6b25hKSwgTkMgKE5vcnRoIENhcm9saW5hKSBhbmQgU0MgKFNPdXRoIENhcm9saW5hKSB3aGVyZSBsZXNzIGV4cGVuc2l2ZSAoJCkgcmVzdGF1cmFudHMgYXJlIGRvbWluYW50LCBhbmQgbW9yZSBleHBlbnNpdmUgcmVzdGF1cmFudHMgYXJlIGFsbW9zdCBub24tZXhpc3RlbnQuDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCmF2ZzEgPC0gZnVuY3Rpb24oZGF0YXNldCwgdmFyMSwgdmFyMikgew0KdmFyMSA8LSBlbnF1byh2YXIxKQ0KdmFyMiA8LSBlbnF1byh2YXIyKQ0KICANCmF2ZzEgIDwtIGRhdGFzZXQgJT4lDQpncm91cF9ieSghIXZhcjEpICU+JQ0Kc3VtbWFyaXNlKGF2ZXJhZ2UgPSBtZWFuKCEhdmFyMikpJT4lDQphcnJhbmdlKGRlc2MoYXZlcmFnZSkpDQphdmcxDQp9DQphdmcxKHJlc3RfMCwgc3RhdGUsIGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNQcmljZVJhbmdlMikNCg0KYGBgDQoNCkFuZCBvZiBjb3Vyc2UgcHJpbnRpbmcgb3V0IHRoZSBhdmVyYWdlIHByaWNlIHJhbmdlIGJ5IHN0YXRlLCB3ZSBzZWUgdGhhdCBRdWViZWMgYW5kIE9udGFyaW8gaGF2ZSBhIG11Y2ggaGlnaGVyIGF2ZXJhZ2UgcHJpY2UgcmFuZ2UgY29tcGFyZWQgdG8gdGhlIG90aGVyIHN0YXRlcyBpbiB0aGUgZGF0YSBzZXQuDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGggPSA3LjV9DQoNCiNUaGlzIGNhbGN1bGF0ZXMgdGhlIGF2ZXJhZ2UgcHJpY2UgcmFuZ2UgaW4gbWFqb3IgTm9ydGggQW1lcmljYW4gY2l0aWVzIGluIHRoZSBkYXRhIHNldA0KDQpyZXN0X2NpdHlfcHJpY2UgPC0gcmVzdF9jaXR5ICU+JQ0KZ3JvdXBfYnkoY2l0eSklPiUNCnN1bW1hcmlzZShuID0gbWVhbihhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIpKQ0KDQojY29tcHV0ZSBub3JtYWxpemVkIHByaWNlcw0KcmVzdF9jaXR5X3ByaWNlJHByaWNlIDwtIHJvdW5kKChyZXN0X2NpdHlfcHJpY2UkbiAtIA0KICBtZWFuKHJlc3RfY2l0eV9wcmljZSRuKSkgLyBzZChyZXN0X2NpdHlfcHJpY2UkbiksIDIpDQogIHJlc3RfY2l0eV9wcmljZSRwcmljZV90eXBlIDwtIGlmZWxzZShyZXN0X2NpdHlfcHJpY2UkcHJpY2UgPCAwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiYmVsb3ciLCAiYWJvdmUiKQ0KDQojIFRoaXMgd2lsbCBjcmVhdGUgb3VyIGRpdmVyZ2luZyBiYXJjaGFydCB3aGljaCBjb21wYXJlcyB0aGUgbm9ybWFsaXplZCBhdmVyYWdlIHByaWNlIHJhbmdlIGFjcm9zcyBjaXRpZXMNCmdncGxvdChyZXN0X2NpdHlfcHJpY2UsIGFlcyhyZW9yZGVyKGNpdHksIC1wcmljZSksIHByaWNlKSwgbGFiZWw9cHJpY2VfdHlwZSkgKyANCiAgZ2VvbV9iYXIoc3RhdD0naWRlbnRpdHknLCBhZXMoZmlsbD1wcmljZV90eXBlKSwgd2lkdGg9LjUpICArDQogIHNjYWxlX2ZpbGxfbWFudWFsKG5hbWU9IlByaWNlcyIsIA0KICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJBYm92ZSBBdmVyYWdlIiwgIkJlbG93IEF2ZXJhZ2UiKSwgDQogICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IGMoImFib3ZlIj0iIzAwYmEzOCIsICJiZWxvdyI9IiNmODc2NmQiKSkgKyANCiAgbGFicyhzdWJ0aXRsZT0iTm9ybWFsaXNlZCBwcmljZXMgZm9yIG9wZXJhdGluZyByZXN0YXVyYW50cyIsIA0KICAgICAgIHRpdGxlPSAiQ29tcGFyaXNvbiBvZiBwcmljZXMgYWNyb3NzIG1ham9yIE5vcnRoIEFtZXJpY2FuIGNpdGllcyIpICsNCiAgbGFicyh4PSJjaXR5IikgKyBjb29yZF9mbGlwKCkNCg0KYGBgDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojQ2FsbCBmdW5jdGlvbiB0byBwcmludCBvdXQgYXZlcmFnZSBwcmljZSByYW5nZXMgYWNyb3NzIGFsbCBOb3J0aCBBbWVyaWNhbiBjaXRpZXMgaW4gZGF0YSBzZXQNCmF2ZzEocmVzdF9jaXR5LCBjaXR5LCBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIpDQpgYGANCg0KV2hlbiB3ZSBsb29rIGF0IGEgY29tcGFyaXNvbiBvZiBwcmljZSByYW5nZXMgYWNyb3NzIGNpdGllcywgdGhlIGZhY3QgdGhhdCBNb250cmVhbCBhbmQgVG9yb250byBoYXZlIHRoZSBoaWdoZXN0IHByaWNlIHJhbmdlcyByb3VnaGx5IGNvaW5jaWRlcyB3aXRoIG91ciBmaW5kaW5ncyBlYXJsaWVyIGluIHdoaWNoIFF1ZWJlYyBhbmQgT250YXJpbyAod2hlcmUgTW9udHJlYWwgYW5kIFRvcm9udG8gYXJlIGxvY2F0ZWQgcmVzcGVjdGl2ZWx5KSBoYWQgdGhlIGhpZ2hlc3QgcHJpY2VkIHJlc3RhdXJhbnRzIGNvbXBhcmVkIHRvIEFtZXJpY2FuIHN0YXRlcy4gDQoNCk9uZSBub3RhYmxlIGV4Y2VwdGlvbiBpcyBTY290dHNkYWxlIGluIEFyaXpvbmEgd2hpY2ggaGFkIG11Y2ggaGlnaGVyIHByaWNlcyB0aGFuIGl0cyBzdXJyb3VuZGluZyBtdW5pY2lwYWxpdGllcyBvZiBQaG9lbml4LCBUZW1wZSBhbmQgTWVzYS4NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDcuNX0NCg0KcmVzdF9jaXR5X3N0YXJzIDwtIHJlc3RfY2l0eSAlPiUNCmdyb3VwX2J5KGNpdHkpJT4lDQpzdW1tYXJpc2UobiA9IG1lYW4oc3RhcnMpKQ0KDQojY29tcHV0ZSBub3JtYWxpemVkIHN0YXJzDQpyZXN0X2NpdHlfc3RhcnMkc3RhcnMgPC0gcm91bmQoKHJlc3RfY2l0eV9zdGFycyRuIC0gDQogIG1lYW4ocmVzdF9jaXR5X3N0YXJzJG4pKS8gc2QocmVzdF9jaXR5X3N0YXJzJG4pLCAyKQ0KcmVzdF9jaXR5X3N0YXJzJHN0YXJzX3R5cGUgPC0gaWZlbHNlKHJlc3RfY2l0eV9zdGFycyRzdGFycyA8IDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJiZWxvdyIsICJhYm92ZSIpDQoNCiMgVGhpcyB3aWxsIGNyZWF0ZSBvdXIgZGl2ZXJnaW5nIGJhcmNoYXJ0IHdoaWNoIGNvbXBhcmVzIHRoZSBub3JtYWxpemVkIGF2ZXJhZ2Ugc3RhcnMgYWNyb3NzIGNpdGllcw0KZ2dwbG90KHJlc3RfY2l0eV9zdGFycywgYWVzKHJlb3JkZXIoY2l0eSwgLXN0YXJzKSwgc3RhcnMpLCANCiAgICAgICBsYWJlbD1zdGFyc190eXBlKSArIA0KICBnZW9tX2JhcihzdGF0PSdpZGVudGl0eScsIGFlcyhmaWxsPXN0YXJzX3R5cGUpLCB3aWR0aD0uNSkgICsNCiAgc2NhbGVfZmlsbF9tYW51YWwobmFtZT0iU3RhcnMiLCANCiAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQWJvdmUgQXZlcmFnZSIsICJCZWxvdyBBdmVyYWdlIiksIA0KICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBjKCJhYm92ZSI9IiMwMGJhMzgiLCAiYmVsb3ciPSIjZjg3NjZkIikpICsgDQogIGxhYnMoc3VidGl0bGU9DQogICAgICAgICAiTm9ybWFsaXNlZCBZZWxwIHN0YXJzIChyYXRpbmdzKSBmb3IgTm9ydGggQW1lcmljYW4gcmVzdGF1cmFudHMiLCANCiAgICAgICB0aXRsZT0gIkNvbXBhcmlzb24gb2YgWWVscCBzdGFycyBhY3Jvc3MgbWFqb3IgTm9ydGggQW1lcmljYW4gY2l0aWVzIikgKyANCiAgbGFicyh4PSJjaXR5IikgKw0KICBjb29yZF9mbGlwKCkNCg0KDQpgYGANCg0KSXQgc2VlbXMgdGhhdCBhbHRob3VnaCB0aGUgcHJpY2UgcmFuZ2Ugb2YgcmVzdGF1cmFudHMgZm9yIFNjb3R0c2RhbGUgYW5kIE1vbnRyZWFsIGFyZSBxdWl0ZSBoaWdoLCB0aGlzIGlzIG1hdGNoZWQgYnkgdGhlIGZhY3QgdGhhdCB0aGUgWWVscCBzdGFycyBmb3IgcmVzdGF1cmFudHMgaW4gdGhlc2UgY2l0aWVzIGFyZSBhbHNvIHJlbGF0aXZlbHkgaGlnaGVyIGNvbXBhcmVkIHRvIG90aGVyIGNpdGllcyBhcyB3ZWxsLiBTbyBwZXJoYXBzIHBheWluZyBhIGxpdHRsZSBtb3JlIGZvciB5b3VyIGZvb2QgbWlnaHQgbm90IGJlIGEgYmFkIGlkZWEhDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojVXNlIHRoZSBmdW5jdGlvbiBhYm92ZSB0byBjYWxjdWxhdGUgdGhlIGF2ZXJhZ2Ugc3RhcnMgYnkgY2l0eSBpbiBkYXRhIHNldA0KYXZnMShyZXN0X2NpdHksIGNpdHksIHN0YXJzKQ0KDQpgYGANCg0KT2YgY291cnNlLCBJIGRlY2lkZWQgdG8gc2VlIGdvIGEgbGl0dGxlIGZ1cnRoZXIgYW5kIHNlZSB3aGF0IHRoZSAidmFsdWUiIHdhcyBmb3IgcmVzdGF1cmFudHMgYWNyb3NzIGRpZmZlcmVudCBjaXRpZXMuIEkgZGVmaW5lIHZhbHVlIGFzIGJlaW5nIHRoZSBudW1iZXIgb2Ygc3RhcnMgZGl2aWRlZCBieSB0aGUgYXZlcmFnZSBwcmljZSByYW5nZS4gV2hhdCB0aGlzIGNhbGN1bGF0ZXMgaXMgdGhlIHRoZSBhbW91bnQgb2YgdmFsdWUgYWRkZWQgdGhhdCB5b3Ugb2J0YWluIGZvciB3aGF0IHlvdSBlYXQgYW5kIHBheSBmb3IgYXQgYSByZXN0YXVyYW50LiBGb3IgZXhhbXBsZSwgYSBjaXR5IHdpdGggcmVzdGF1cmFudHMgdGhhdCBoYXZlIGEgaGlnaGVyIGF2ZXJhZ2UgbnVtYmVyIG9mIHN0YXJzIG9yIGEgbG93ZXIgcHJpY2UgcmFuZ2Ugd2lsbCBkZWxpdmVyIG1vcmUgdmFsdWUgZm9yIHlvdXIgZG9sbGFyIHRoYW4gdGhvc2UgdGhhdCBoYXZlIGxvd2VyIG51bWJlciBvZiBzdGFycyBvciBhIGhpZ2hlciBwcmljZSByYW5nZS4NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDcuNX0NCiNDb2RlIGZvciBjYWxjdWxhdGluZyBhIGRpdmVyZ2luZyBiYXIgcGxvdCBvZiBwcmljZSB0byBzdGFycyByYXRpbywgdGhpcyBkZXRlcm1pbmVzIHRoZSB2YWx1ZSBvZiBhIHJlc3RhdXJhbnQsIGFzIGluIGJhbmcgZm9yIHlvdXIgYnVjaw0KDQpyZXN0X2NpdHkkdmFsdWUgPC0gICByZXN0X2NpdHkkc3RhcnMvcmVzdF9jaXR5JGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNQcmljZVJhbmdlMg0KDQpyZXN0X2NpdHlfdmFsdWUgPC0gcmVzdF9jaXR5ICU+JQ0KZ3JvdXBfYnkoY2l0eSklPiUNCnN1bW1hcmlzZShuID0gbWVhbih2YWx1ZSkpDQoNCiNjb21wdXRlIG5vcm1hbGl6ZWQgcHJpY2VzDQpyZXN0X2NpdHlfdmFsdWUkdmFsdWUgPC0gcm91bmQoKHJlc3RfY2l0eV92YWx1ZSRuIC0gDQogIG1lYW4ocmVzdF9jaXR5X3ZhbHVlJG4pKS8gc2QocmVzdF9jaXR5X3ZhbHVlJG4pLCAyKQ0KcmVzdF9jaXR5X3ZhbHVlJHZhbHVlX3R5cGUgPC0gaWZlbHNlKHJlc3RfY2l0eV92YWx1ZSR2YWx1ZSA8IDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJiZWxvdyIsICJhYm92ZSIpDQoNCiMgVGhpcyB3aWxsIGNyZWF0ZSBvdXIgZGl2ZXJnaW5nIGJhcmNoYXJ0IHdoaWNoIGNvbXBhcmVzIHRoZSBub3JtYWxpemVkIHZhbHVlIGFjcm9zcyBjaXRpZXMNCmdncGxvdChyZXN0X2NpdHlfdmFsdWUsIGFlcyhyZW9yZGVyKGNpdHksIC12YWx1ZSksIHZhbHVlKSwgbGFiZWw9dmFsdWVfdHlwZSkgKyANCiAgZ2VvbV9iYXIoc3RhdD0naWRlbnRpdHknLCBhZXMoZmlsbD12YWx1ZV90eXBlKSwgd2lkdGg9LjUpICArDQogIHNjYWxlX2ZpbGxfbWFudWFsKG5hbWU9InZhbHVlIiwgDQogICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkFib3ZlIEF2ZXJhZ2UiLCAiQmVsb3cgQXZlcmFnZSIpLCANCiAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYygiYWJvdmUiPSIjMDBiYTM4IiwgImJlbG93Ij0iI2Y4NzY2ZCIpKSArIA0KICBsYWJzKHN1YnRpdGxlPSJOb3JtYWxpc2VkIFllbHAgdmFsdWUgKHJhdGluZ3MpIGZvciBOb3J0aCBBbWVyaWNhbiBjaXRpZXMiLCANCiAgICAgICB0aXRsZT0gDQogICAgICAgICAiQ29tcGFyaXNvbiBvZiByZXN0YXVyYW50IHZhbHVlIGFjcm9zcyBtYWpvciBOb3J0aCBBbWVyaWNhbiBjaXRpZXMiKSArIA0KICBsYWJzKHg9ImNpdHkiKSArDQogIGNvb3JkX2ZsaXAoKQ0KDQoNCg0KYGBgDQoNCldlIGZpbmQgdGhhdCB0aGUgY2l0aWVzIG9mIHRoZSBQaG9lbml4IG1ldHJvcG9saXRhbiBhcmVhIHN1Y2ggYXMgUGhvZW5peCwgTWVzYSwgYW5kIFRlbXBlIHRvIGJlIGFib3ZlIGF2ZXJhZ2UgaW4gdGVybXMgb2YgZGVsaXZlcmluZyB2YWx1ZSBmb3IgdGhlIGN1c3RvbWVyLCB3aGlsZSBjaXRpZXMgc3VjaCBhcyBUb3JvbnRvIGFuZCBNb250cmVhbCBpbiBDYW5hZGEgYWxvbmcgd2l0aCBTY290dHNkYWxlIGRvIG5vdCBkZWxpdmVyIGFzIG11Y2ggdmFsdWUgZm9yIHRoZSBzYW1lIGFtb3VudCBvZiBtb25leSBiZWluZyBzcGVudC4NCg0KV2hpbGUgd2UgYXJlIG9uIHRoZSB0b3BpYyBvZiBwcmljZSBhbmQgcmVzdGF1cmFudHMsIEkgd2FudCB0byBleHBsb3JlIGEgYml0IGFuZCBsb29rIGF0IGEgbmV3IHZhcmlhYmxlIGNhbGxlZCBhdHRpcmUgYW5kIHNlZSBpZiB0aGUgcGVyY2VudGFnZSBvZiB0aG9zZSBleHBlbnNpdmUgMy00IHJlc3RhdXJhbnRzIGxpbmUgdXAgd2l0aCB0aGUgcGVyY2VudGFnZSBvZiByZXN0YXVyYW50cyB3aGVyZSBtb3JlIGZvcm1hbCBhdHRpcmUgaXMgbmVlZGVkLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoID0gNy41fQ0KDQojTmV4dCBwbG90IGlzIGZvciBjYXN1YWwgdnMuIGZvcm1hbCB2cy4gZHJlc3N5IGFjcm9zcyBzdGF0ZXMgYW5kIGNpdGllcyBmb3IgcmVzdGF1cmFudHMuDQojRGF0YSBvbmx5IGluY2x1ZGVzIG9wZXJhdGluZyBlc3RhYmxpc2htZW50cyBpbiBOb3J0aCBBbWVyaWNhbiBzdGF0ZXMgd2hlcmUgdGhlIGF0dGlyZSB2YWx1ZSBpcyBrbm93bg0KcmVzdGF1cmFudF9kcmVzcyA8LSBzdWJzZXQoeWVscF9mbGF0MSwgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNBdHRpcmUpICYgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNQcmljZVJhbmdlMikgJiBpc19vcGVuID09IDEgJiAhaXMubmEoYXR0cmlidXRlcy5SZXN0YXVyYW50c1Rha2VPdXQpICYgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNEZWxpdmVyeSkgJiAhaXMubmEoYXR0cmlidXRlcy5SZXN0YXVyYW50c1RhYmxlU2VydmljZSkgJiAhaXMubmEoYXR0cmlidXRlcy5Ob2lzZUxldmVsKSkNCg0KDQojQ2FsbGluZyB0aGUgc2FtZSBmdW5jdGlvbiB1c2VkIHRvIG91dHB1dCB0aGUgZGF0YXNldHMgdXNpbmcgdGhlIHZhcmlhYmxlIGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNBdHRpcmUgaW5zdGVhZCBvZiBwcmljZSByYW5nZQ0KcmVzdGF1cmFudF9mbjIocmVzdGF1cmFudF9kcmVzcywgcmVzdGF1cmFudF9hdHRpcmUsIHN0YXRlLCBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzQXR0aXJlKQ0KDQoNCmdncGxvdChkYXRhID0gcmVzdGF1cmFudF9hdHRpcmUsIGFlcyh4ID0gc3RhdGUsIHkgPSBwZXJjZW50LCBmaWxsPWF0dHJpYnV0ZXMuUmVzdGF1cmFudHNBdHRpcmUpKSArIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDAuNSkgKw0Kc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lPSJBdHRpcmUiLCBsYWJlbHM9YygiQ2FzdWFsIiwgIkRyZXNzeSIsICJGb3JtYWwiKSkgKyBsYWJzKHRpdGxlID0gIlBlcmNlbnRhZ2Ugb2YgcmVzdGF1cmFudHMgYnkgYXR0aXJlIikgICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICANCg0KDQpgYGANCg0KSW4gZmFjdCwgd2Ugc2VlIHRoYXQgdGhlIHBlcmNlbnRhZ2Ugb2YgZHJlc3N5IGFuZCBmb3JtYWwgYXR0aXJlIGRvZXMgc29ydCBvZiBsaW5lIHVwIHdpdGggdGhlIHBlcmNlbnRhZ2Ugb2YgZXhwZW5zaXZlIChjYXRlZ29yeSAzLTQpIHJlc3RhdXJhbnRzIHRoYXQgd2Ugc2F3IGluIHRoZSBzdGFja2VkIGJhciBwbG90IGVhcmxpZXIuIEluIGZhY3QsIHRoZSBwZXJjZW50YWdlIG9mIGRyZXNzeSByZXN0YXVyYW50cyBhY3R1YWxseSBleGNlZWRzIHRob3NlIGluIHRoZSBwcmljZSBjYXRlZ29yeSBvZiA0LCBzbyBpdCBjb3VsZCBiZSB0aGUgY2FzZSB0aGF0IHRoZXJlIGFyZSBzb21lIG9mIHRob3NlIG1vcmUgZXhwZW5zaXZlIHJlc3RhdXJhbnRzIGluIHRoZSAzIHByaWNlIHJhbmdlIHRoYXQgbWF5IHdhbnQgcGVvcGxlIHRvIGNvbWUgaW4gd2l0aCBhIGRyZXNzeSBhdHRpcmUuIFRoYXQgYmVpbmcgc2FpZCwgdGhlIHBlcmNlbnRhZ2Ugb2YgcmVzdGF1cmFudHMgcmVxdWlyaW5nIGZvcm1hbCBhdHRpcmUgaXMgYWxtb3N0IG5vbi1leGlzdGVudCBhY3Jvc3MgYW55IE5vcnRoIEFtZXJpY2FuIHN0YXRlLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQphdHRpcmVfcHJpY2UgPC0gbG0oYXR0cmlidXRlcy5SZXN0YXVyYW50c1ByaWNlUmFuZ2UyIH4gYXR0cmlidXRlcy5SZXN0YXVyYW50c0F0dGlyZSwgZGF0YSA9IHN1YnNldChyZXN0YXVyYW50X2RyZXNzKSkNCnN1bW1hcnkoYXR0aXJlX3ByaWNlKQ0KDQoNCmBgYA0KDQpSZWxhdGl2ZSB0byBjYXN1YWwgYXR0aXJlLCBkcmVzc3kgYW5kIGZvcm1hbCBhdHRpcmUgcG9zaXRpdmVseSBwcmVkaWN0ZWQgd2hldGhlciBvciBub3QgYSByZXN0YXVyYW50cyBwcmljZSByYW5nZSB3YXMgbW9yZSBleHBlbnNpdmUgb3Igbm90LiBQZXJoYXBzIGR1ZSB0byB0aGUgbGFjayBvZiByZXN0YXVyYW50cyByZXF1aXJpbmcgZm9ybWFsIGF0dGlyZSwgdGhlIGltcGFjdCBvZiBkcmVzc3kgYXR0aXJlIG9uIHByZWRpY3RpbmcgYSByZXN0YXVyYW50cyBwcmljZSByYW5nZSB3YXMgZ3JlYXRlciB0aGFuIGZvciBmb3JtYWwgYXR0aXJlLiBJbiB0aGlzIGNhc2UsIHRoZSByZWdyZXNzaW9uIGNhbiBiZSBwcmVkaWN0ZWQgYXMgc3VjaCB0aGF0IGRyZXNzeSBhdHRpcmUgaXMgZ2VuZXJhbGx5IDEuNiBoaWdoZXIgKHJlbGF0aXZlIHRvIGNhc3VhbCkgaW4gdGVybXMgb2YgcHJpY2UgcmFuZ2Ugb24gYXZlcmFnZSAob3V0IG9mIDQpLCB3aGlsZSB0aGUgcHJpY2UgcmFuZ2UgaXMgb25seSAwLjYgaGlnaGVyIGZvciBmb3JtYWwgYXR0aXJlIChyZWxhdGl2ZSB0byBjYXN1YWwpLg0KSXQgaXMgYWxzbyBvZiBpbnRlcmVzdCB0aGF0IDE1JSBvZiB2YXJpYW5jZSBpbiB0ZXJtcyBvZiBwcmVkaWNpbmcgcHJpY2UgcmFuZ2UgaXMgZXhwbGFpbmVkIGJ5IGF0dGlyZSBvbiBpdHMgb3duLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoID0gNy41fQ0KDQojQ3JlYXRlIGEgbmV3IHZhcmlhYmxlIGNhbGxlZCBmdWxsX3NlcnZpY2UgdGhhdCByZXByZXNlbnRzIHRoYXQgYSByZXN0YXVyYW50IGRvZXMgdGFrZW91dCwgZGVsaXZlcnkgYW5kIHRhYmxlIHNlcnZpY2UgKGVzc2VudGlhbGx5IGEgZGluZS1pbiByZXN0YXVyYW50KQ0KDQpyZXN0XzAkRGVsaXZlcnlfc2VydmljZSA8LSBpZmVsc2UocmVzdF8wJGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNEZWxpdmVyeSA9PSAxLCANCiAgVFJVRSwgRkFMU0UpDQpyZXN0XzAkVGFrZW91dF9zZXJ2aWNlIDwtIGlmZWxzZShyZXN0XzAkYXR0cmlidXRlcy5SZXN0YXVyYW50c1Rha2VPdXQgPT0gMSwgDQogIFRSVUUsIEZBTFNFKQ0KcmVzdF8wJFRhYmxlX3NlcnZpY2UgPC0gaWZlbHNlKHJlc3RfMCRhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzVGFibGVTZXJ2aWNlID09IDEsIA0KICBUUlVFLCBGQUxTRSkNCg0KcmVzdF8wJEZ1bGxfc2VydmljZSA8LSAgaWZlbHNlKCByZXN0XzAkYXR0cmlidXRlcy5SZXN0YXVyYW50c1RhYmxlU2VydmljZSA9PSAxICYNCiAgcmVzdF8wJGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNUYWtlT3V0ID09IDEgJg0KICByZXN0XzAkYXR0cmlidXRlcy5SZXN0YXVyYW50c0RlbGl2ZXJ5ID09MSwgVFJVRSwgRkFMU0UpDQoNCiNBbm90aGVyIHF1ZXN0aW9uIHRvIGFuc3dlciwgaXMgcGVyY2VudGFnZSBvZiByZXN0YXVyYW50cyBvZiB0b3RhbCBudW1iZXIgb2YgZXN0YWJsaXNobWVudHMgaW4gZWFjaCBzdGF0ZQ0KI1RoZSBjb2RlIGJlbG93IGNhbGN1bGF0ZXMgdGhlIHBlcmNlbnRhZ2Ugb2YgImZ1bGwtc2VydmljZSIgcmVzdGF1cmFudHMgYXMgYSBwZXJjZW50YWdlIG9mIHRvdGFsIG9wZW4gcmVzdGF1cmFudHMgb24gWWVscA0KDQpyZXN0X3NlcnZpY2UgPC0gcmVzdF8wICU+JQ0KZ3JvdXBfYnkoc3RhdGUsIEZ1bGxfc2VydmljZSklPiUNCnN1bW1hcmlzZShuPW4oKSklPiUNCm11dGF0ZSh0b3RhbCA9IHN1bShuKSkgJT4lDQptdXRhdGUocGVyY2VudCA9IHJvdW5kKChuLyB0b3RhbCkqMTAwLCAxKSkNCg0KDQpnZ3Bsb3QoZGF0YSA9IHJlc3Rfc2VydmljZSwgYWVzKHggPSBzdGF0ZSwgeSA9IHBlcmNlbnQsIGZpbGw9IEZ1bGxfc2VydmljZSkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMC41KSArIA0KICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWU9IkZ1bGwgc2VydmljZSIsIA0KICBsYWJlbHM9YygiTm8gZnVsbCBzZXJ2aWNlIiwgIkZ1bGwgc2VydmljZSIpKSArIA0KICBsYWJzKHRpdGxlID0gIlBlcmNlbnRhZ2Ugb2YgcmVzdGF1cmFudHMgYnkgZnVsbCBzZXJ2aWNlIikgKyANCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICANCg0KDQoNCmBgYA0KDQpMZXQgdXMgbG9vayBhdCBsaXR0bGUgYml0IGZ1cnRoZXIgaW50byBkaW5pbmcgb3B0aW9ucyBhdCBhIHJlc3RhdXJhbnQuIEEgZ29vZCByZXN0YXVyYW50IHNob3VsZCBhbHdheXMgcHJvdmlkZSBhIGxhcmdlIHZhcmlldHkgb2YgZGluaW5nIG9wdGlvbnMsIGFuZCBzbyBJIGhhdmUgY29uc3RydWN0ZWQgYSB2YXJpYWJsZSBjYWxsZWQgIkZ1bGxfc2VydmljZSIgdGhhdCBoYXMgYSB2YWx1ZSBvZiAxIHdoZW5ldmVyIGRlbGl2ZXJ5LCB0YWtlb3V0IGFuZCB0YWJsZSBzZXJ2aWNlcyBhcmUgYWxsIHByb3ZpZGVkLCBhbmQgMCB3aGVuZXZlciBldmVuIG9uZSBvZiB0aGVzZSBzZXJ2aWNlcyB3ZXJlIG5vdCBwcm92aWRlZC4NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDEwfQ0KDQpyZXN0X3NlcnZpY2UxIDw8LSByZXN0XzAgJT4lDQpncm91cF9ieShzdGF0ZSwgRGVsaXZlcnlfc2VydmljZSklPiUNCnN1bW1hcmlzZShuPW4oKSklPiUNCm11dGF0ZSh0b3RhbCA9IHN1bShuKSkgJT4lDQptdXRhdGUocGVyY2VudCA9IHJvdW5kKChuLyB0b3RhbCkqMTAwLCAxKSkgDQoNCnJzMSA8LSBnZ3Bsb3QoZGF0YSA9IHJlc3Rfc2VydmljZTEsIGFlcyh4ID0gc3RhdGUsIHkgPSBwZXJjZW50LCANCiAgZmlsbD0gRGVsaXZlcnlfc2VydmljZSkpICsgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMC41KSArIA0KICBzY2FsZV9maWxsX2Rpc2NyZXRlKG5hbWU9IkRlbGl2ZXJ5IHNlcnZpY2UiLCANCiAgbGFiZWxzPWMoIk5vIGRlbGl2ZXJ5IHNlcnZpY2UiLCAiRGVsaXZlcnkgc2VydmljZSIpKSArIA0KICBsYWJzKHRpdGxlID0gIiUgRGVsaXZlcnkgc2VydmljZSIpICsgDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArIA0KICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSArIGxhYnMoeSA9IE5VTEwpDQoNCnJlc3Rfc2VydmljZTIgPDwtIHJlc3RfMCAlPiUNCmdyb3VwX2J5KHN0YXRlLCBUYWJsZV9zZXJ2aWNlKSU+JQ0Kc3VtbWFyaXNlKG49bigpKSU+JQ0KbXV0YXRlKHRvdGFsID0gc3VtKG4pKSAlPiUNCm11dGF0ZShwZXJjZW50ID0gcm91bmQoKG4gLyB0b3RhbCkqMTAwLCAxKSkgDQoNCnJzMiA8LSBnZ3Bsb3QoZGF0YSA9IHJlc3Rfc2VydmljZTIsIA0KICBhZXMoeCA9IHN0YXRlLCB5ID0gcGVyY2VudCwgZmlsbD0gVGFibGVfc2VydmljZSkpICsgDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDAuNSkgKyANCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lPSJUYWJsZSBzZXJ2aWNlIiwgDQogIGxhYmVscz1jKCJObyB0YWJsZSBzZXJ2aWNlIiwgIlRhYmxlIHNlcnZpY2UiKSkgKyANCiAgbGFicyh0aXRsZSA9ICIlIFRhYmxlIHNlcnZpY2UiKSArIA0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKyAgdGhlbWUoIGF4aXMudGlja3MueT1lbGVtZW50X2JsYW5rKCkpICsgIA0KICB0aGVtZSggYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpKSAgKyBsYWJzKHkgPSBOVUxMKQ0KDQpyZXN0X3NlcnZpY2UzIDw8LSByZXN0XzAgJT4lDQpncm91cF9ieShzdGF0ZSwgVGFrZW91dF9zZXJ2aWNlKSU+JQ0Kc3VtbWFyaXNlKG49bigpKSU+JQ0KbXV0YXRlKHRvdGFsID0gc3VtKG4pKSAlPiUNCm11dGF0ZShwZXJjZW50ID0gcm91bmQoKG4vIHRvdGFsKSoxMDAsIDEpKSANCg0KcnMzIDwtIGdncGxvdChkYXRhID0gcmVzdF9zZXJ2aWNlMywgDQogIGFlcyh4ID0gc3RhdGUsIHkgPSBwZXJjZW50LCBmaWxsPSBUYWtlb3V0X3NlcnZpY2UpKSArIA0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAwLjUpICsgDQogIHNjYWxlX2ZpbGxfZGlzY3JldGUobmFtZT0iVGFrZW91dCBzZXJ2aWNlIiwgDQogIGxhYmVscz1jKCJObyB0YWtlb3V0IHNlcnZpY2UiLCAiVGFrZW91dCBzZXJ2aWNlIikpICsgDQogIGxhYnModGl0bGUgPSAiJSBUYWtlIG91dCBzZXJ2aWNlIikgKyANCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsgDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsgIHRoZW1lKCBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpKSArICANCiAgdGhlbWUoIGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSkgICsgbGFicyh5PU5VTEwpDQoNCg0KZ3JpZC5hcnJhbmdlKHJzMSwgcnMyLCByczMsIG5jb2wgPSAzLCANCiAgICAgICAgICAgICB0b3AgPSAiUGVyY2VudGFnZSBvZiByZXN0YXVyYW50cyBieSB0eXBlIG9mIHNlcnZpY2UiKSANCg0KI3NvdXJjZSgiaHR0cDovL3BldGVyaGFzY2hrZS5jb20vQ29kZS9tdWx0aXBsb3QuUiIpDQojbXVsdGlwbG90KHJzMSwgcnMyLCByczMsIGNvbHMgPTMpDQoNCmBgYA0KDQpJdCBzZWVtcyB0aGF0IHZlcnkgZmV3IG9wZXJhdGluZyByZXN0YXVyYW50cyBkbyBkZWxpdmVyeSwgdGFrZS1vdXQgYW5kIGRpbmUtaW4gYWxsIGF0IG9uY2UuDQpUaGUgbWFpbiByZWFzb24gZm9yIHRoaXMgbGFjayBvZiBmdWxsIHNlcnZpY2Ugb2ZmZXJpbmdzIGlzIHByZWRvbWluYXRlbHkgZHVlIHRvIHRoZSBsYWNrIG9mIGRlbGl2ZXJ5IHNlcnZpY2UgYmVpbmcgb2ZmZXJlZCBhY3Jvc3MgcmVzdGF1cmFudHMgKGFyb3VuZCAyMC0yNSUgb2YgcmVzdGF1cmFudHMgZG8gaXQpLiBIb3dldmVyLCB2aXJ0dWFsbHkgYWxsIHJlc3RhdXJhbnRzIG9mZmVyIHRha2Ugb3V0IHNlcnZpY2Ugd2l0aCB0aGUgbm90YWJsZSBleGNlcHRpb24gb2YgUXVlYmVjIGhhdmluZyBhIG11Y2ggbG93ZXIgcGVyY2VudGFnZSB3aGlsZSBhbHNvIHNpbXVsdGFuZW91c2x5IGhhdmluZyBtb3JlIHJlc3RhdXJhbnRzIHRoYXQgYXJlIGFyZSBkaW5lLWluIHdpdGggdGFibGUgc2VydmljZS4NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCg0KI0NvZGUgYmVsb3cgaXMgdG8gcHJvZHVjZSBhIG1hcCBzaG93aW5nIHdoZXJlIG9wZXJhdGluZyByZXN0YXVyYW50cyBhcmUgd2l0aGluIGVhY2ggY2l0eS4gDQojQ29kZSB3YXMgbWFkZSBhcyBmbGV4aWJsZSBhcyBwb3NzaWJsZSB0byBhY2NvdW50IGZvciBkaWZmZXJlbnQgdmFyaWFibGVzIHN1Y2ggYXMgbG9uZ2l0dWRlLCBsYXRpdHVkZSwgdGl0bGUgbmFtZSwgY29sb3VyIG9mIGRvdHMsIGRhdGEgc2V0IGFzIHdlbGwgYXMgdGhlIGNpdHkNCg0KDQp5ZWxwX2NpdGllczAgPC0gZnVuY3Rpb24oZGF0YXNldCwgY2l0eTEsIGxvbmcxLCBsb25nMiwgbGF0MSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgbGF0MiwgdGl0bGVuYW1lLCBjb2xvcjEpIHsNCg0KeWVscF90bzEgPC0gc3Vic2V0KGRhdGFzZXQsIGNpdHkgPT0gY2l0eTEgJiANCiAgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNQcmljZVJhbmdlMikgJiAhaXMubmEoaXNfb3BlbikgJiANCiAgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNUYWtlT3V0KSAmIA0KICAhaXMubmEoYXR0cmlidXRlcy5SZXN0YXVyYW50c0RlbGl2ZXJ5KSAmIA0KICAhaXMubmEoYXR0cmlidXRlcy5SZXN0YXVyYW50c1RhYmxlU2VydmljZSkpDQoNCnNiYm94IDwtIG1ha2VfYmJveChsb24gPSB5ZWxwX3RvMSRsb25naXR1ZGUsIGxhdCA9IHllbHBfdG8xJGxhdGl0dWRlLCBmID0gMC4wMSkgDQp0b19tYXAgPC0gZ2V0X21hcChsb2NhdGlvbiA9IHNiYm94LCBtYXB0eXBlID0gInJvYWRtYXAiLCBzY2FsZSA9IDIsIA0KICAgICAgICAgICAgICAgICAgY29sb3I9ImJ3Iiwgem9vbSA9IDEwKQ0KDQpnZ21hcCh0b19tYXApICsNCiAgZ2VvbV9wb2ludChkYXRhPXllbHBfdG8xLCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlKSwgY29sb3IgPSBjb2xvcjEsDQogIHNpemUgPSAxLjUsIGFscGhhID0gMC4zKSArIHNjYWxlX3hfY29udGludW91cyhsaW0gPSBjKGxvbmcxLCBsb25nMikpICsgDQogIHNjYWxlX3lfY29udGludW91cyhsaW0gPSBjKGxhdDEsIGxhdDIpKSArICB4bGFiKCdMb25naXR1ZGUnKSArIA0KICB5bGFiKCdMYXRpdHVkZScpICsgZ2d0aXRsZSh0aXRsZW5hbWUpICsgZ3VpZGVzKGNvbG9yPUZBTFNFKSArIA0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKyBnZW9tX2ppdHRlcigpDQp9DQp5ZWxwX2NpdGllczAoeWVscF9mbGF0MSwgIlRvcm9udG8iLCAtNzkuNiwgLTc5LjIsIDQzLjU4LCA0My44MSwgDQogICAgICAgICAgICAgIkxvY2F0aW9uIG9mIHJlc3RhdXJhbnRzIGluIFRvcm9udG8iLCAiI2ZjOTI3MiIpDQoNCg0KDQpgYGANCg0KTW9zdCBvZiB0aGUgYW5hbHlzaXMgc28gZmFyIGhhcyBiZWVuIG9uIGEgc3RhdGUgbGV2ZWwsIGFuZCBzbyBJIHdvdWxkIGxpa2UgdG8gZGVsdmUgbW9yZSBpbnRvIGFuYWx5emluZyByZXN0YXVyYW50cyBvciBlc3RhYmxpc2htZW50cyBpbiBnZW5lcmFsIG9uIGEgY2l0eSBsZXZlbCB3aXRoIGFuIGVtcGhhc2lzIG9uIGdlb2dyYXBoaWNhbCBkaXN0cmlidXRpb24gb2YgcmVzdGF1cmFudHMgYWNyb3NzIGRpZmZlcmVudCB2YXJpYWJsZXMuIFNvbWUgcXVlc3Rpb25zIHRoYXQgSSByZWFsbHkgd2FudCB0byBleHBsb3JlIGFyZTogDQoNCjEpIFdoZXJlIHdpdGhpbiBlYWNoIGNpdHkgYXJlIHJlc3RhdXJhbnRzIGxvY2F0ZWQ/IEFyZSB0aGV5IGV2ZW5seSBzcHJlYWQgYWNyb3NzIGRvd250b3duIGFuZCBzdWJ1cmJhbiBhcmVhcz8NCjIpIEFuZCBob3cgZG9lcyB0aGlzIHZhcnkgYnkgcHJpY2UgcmFuZ2U/DQozKSBBbmQgYXJlIGhpZ2hlciByYXRlZCByZXN0YXVyYW50cyBtb3JlIGNvbmNlbnRyYXRlZCBpbiBjZXJ0YWluIHBhcnRzIG9mIHRoZSBjaXR5Pw0KNCkgQXJlIG5vaXNpZXIgcmVzdGF1cmFudHMgc3ByZWFkIG91dCBhY3Jvc3MgdGhlIGNpdHkgb3IgYXJlIHRoZXkgbWFpbmx5IGluIHRoZSBkb3dudG93biBjb3JlPw0KNSkgQXJlIGFsY29ob2wgc2VydmljZSBsZXZlbHMgaW4gcmVzdGF1cmFudHMgY29uc2lzdGVudCB0aHJvdWdob3V0IGRpZmZlcmVudCBwYXJ0cyBvZiB0aGUgY2l0eT8NCkFuZCBsYXN0bHk6DQo2KSBXaGVyZSBhcmUgc29tZSBnb29kIHBsYWNlcyBmb3IgZGlubmVyPw0KDQpJbiB0aGlzIGdlb2dyYXBoaWMgYW5hbHlzaXMsIEkgYW0gZ29pbmcgdG8gZm9jdXMgb24gdGhyZWUgY2l0aWVzLCBUb3JvbnRvLCBNb250cmVhbCBhbmQgUGhvZW5peCwgYW5kIHRoaXMgaXMgYmVjYXVzZSB0aGVzZSB0aHJlZSBjaXRpZXMgd2VyZSBhbW9uZyB0aGUgdG9wIDMtNCBjaXRpZXMgdGhhdCBoYWQgdGhlIG1vc3QgcmVzdGF1cmFudHMgcmVwcmVzZW50ZWQgd2l0aGluIFllbHAuIEkgYWxzbyBicmllZmx5IGV4YW1pbmUgU2NvdHRzZGFsZSAod2hpY2ggaXMgdG8gdGhlIG5vcnRoZWFzdCBvZiBQaG9lbml4KSBiZWNhdXNlIGl0IG1pZ2h0IGJlIGludGVyZXN0aW5nIHRvIGFuYWx5emUgYXMgdGhlIHRoZSBjaXR5IHNlZW1zIHRvIGhhdmUgbXVjaCBoaWdoZXIgcmVzdGF1cmFudCBwcmljZXMgZGVzcGl0ZSBpdHMgcHJveGltaXR5Lg0KDQoNCkluIFRvcm9udG8sIHJlc3RhdXJhbnRzIGFyZSBtYWlubHkgY29uY2VudHJhdGVkIGluIHRoZSBkb3dudG93biBjb3JlLCBhbmQgaGF2ZSBhIGxhcmdlIGNvbmNlbnRyYXRlZCBwcmVzZW5jZSBhbG9uZyB0aGUgbWFpbiB0aG9yb3VnaGZhcmUgWW9uZ2UgU3RyZWV0IHdoaWNoIGV4dGVuZHMgYWxsIHRoZSB1cCB2ZXJ0aWNhbGx5IHRocm91Z2ggdGhlIGNlbnRyZSBvZiB0aGUgbWFwLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQp5ZWxwX2NpdGllczAoeWVscF9mbGF0MSwgIk1vbnRy6WFsIiwgLTczLjc2LCAtNzMuNTIsIDQ1LjQyLCA0NS42LCANCiAgICAgICAgICAgICAiTG9jYXRpb24gb2YgcmVzdGF1cmFudHMgaW4gTW9udHJlYWwiLCAiI2ZjOTI3MiIpDQoNCmBgYA0KDQpJbiBNb250cmVhbCwgdGhlIHJlc3RhdXJhbnRzIGFyZSBldmVuIG1vcmUgY29uY2VudHJhdGVkLCBwYXJ0aWN1bGFybHkgaW4gdGhlIGRvd250b3duIGNvcmUgYW5kIGluIHRoZSBQbGF0ZWF1LU1vbnQtUm95YWwgYXJlYSBqdXN0IGRpcmVjdGx5IHRvIHRoZSBub3J0aHdlc3Qgb2YgdGhlIGRvd250b3duIGFyZWEuIFJlc3RhdXJhbnRzIG91dHNpZGUgdGhpcyBhcmVhIGFyZSBmYWlybHkgc3ByZWFkIG91dCBhbmQgYXJlIG11Y2ggbG93ZXIgaW4gbnVtYmVyLCB3aGljaCBwYXJ0bHkgaGFzIHRvIGRvIHdpdGggdGhlIGZhY3QgdGhhdCBNb250cmVhbCBpcyBhIG11Y2ggbW9yZSBkZW5zZWx5IHBvcHVsYXRlZCBjaXR5IHRoYW4gVG9yb250by4NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnllbHBfY2l0aWVzMCh5ZWxwX2ZsYXQxLCAiUGhvZW5peCIsIC0xMTIuMjM1LCAtMTExLjk1LCAzMy4zOTUsIDMzLjYzLCANCiAgICAgICAgICAgICAiTG9jYXRpb24gb2YgcmVzdGF1cmFudHMgaW4gUGhvZW5peCIsICIjZmM5MjcyIikNCmBgYA0KDQpJbiBQaG9lbml4LCByZXN0YXVyYW50cyBzZWVtIHRvIGJlIHNwcmVhZCBldmVubHkgYWNyb3NzIHRoZSBjaXR5IGluIGEgZ3JpZC1saWtlIHBhdHRlcm4gd2l0aCBhIHNsaWdodGx5IGxhcmdlciBjb25jZW50cmF0aW9uIGluIHRoZSBkb3dudG93biBzb3V0aGNlbnRyYWwgc3F1YXJlIGFyZWEgaW4gdGhlIG1pZGRsZSBvZiB0aGUgbWFwICh3aXRoIGFsbCBmb3VyIGhpZ2h3YXlzIHN1cnJvdW5kaW5nIGl0KS4gT25lIGNhbiBhbHNvIHNlZSBvbiB0aGUgbWFwIHRoYXQgdG8gdGhlIGVhc3QgYXJlIFNjb3R0ZGFsZSBhbmQgVGVtcGUsIGJvdGggb2Ygd2hpY2ggYXJlIHNlcGFyYXRlIGNpdGllcyByZXByZXNlbnRlZCB3aXRoaW4gdGhlIFllbHAgZGF0YSBzZXQgKHRob3VnaCBub3QgdmVyeSB3ZWxsIHJlcHJlc2VudGVkIGNvbXBhcmVkIHRvIFBob2VuaXgpLiBOb25ldGhlbGVzcywgSSBkZWNpZGUgdG8gdGFrZSBhIGZ1cnRoZXIgbG9vayBhdCBsZWFzdCBzcGVjaWZpY2FsbHkgaW50byBTY290dHNkYWxlIChvbmUgb2YgdGhlIGxhcmdlciBjaXRpZXMganVzdCBvdXRzaWRlIFBob2VuaXgpIGFueXdheS4NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnllbHBfY2l0aWVzMCh5ZWxwX2ZsYXQxLCAiU2NvdHRzZGFsZSIsIC0xMTIsIC0xMTEuODUsIDMzLjQ0LCAzMy42LA0KICAgICAgICAgICAgICJMb2NhdGlvbiBvZiByZXN0YXVyYW50cyBpbiBTY290dHNkYWxlIiwgIiNmYzkyNzIiKQ0KYGBgDQoNClRoZSBjb25jZW50cmF0aW9uIG9mIHJlc3RhdXJhbnRzIGluIFNjb3R0c2RhbGUgc2VlbXMgdG8gYmUgYWxvbmcgb25lIG5hcnJvdyB2ZXJ0aWNhbCBzdHJlZXQga25vd24gYXMgU2NvdHRzYWxlIFJvYWQuIFRoZSByZXN0YXVyYW50cyBpbiBTY290dHNkYWxlIGFyZSBtdWNoIG1vcmUgY29uY2VudHJhdGVkIGluIHNwZWNpZmljIGFyZWFzIHRoYW4gd2FzIHRoZSBjYXNlIHdpdGggUGhvZW5peCB3aGljaCBpcyBqdXN0IHRvIHRoZSB3ZXN0IG9mIHRoZSBjaXR5Lg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQojVGhpcyBmdW5jdGlvbiBpcyBzaW1pbGFyIHRoZSB5ZWxwX2NpdGllczAgZXhjZXB0IHRoYXQgdGhpcyBjb2RlIGdlbmVyYXRlcw0KIzQgcGxvdHMgKG9uZSBmb3IgZWFjaCBwcmljZSByYW5nZSkgYWxsb3dpbmcgdXMgdG8gc2VlIHRoZSBkaXN0cmlidXRpb24gb2YgDQojdGhlIHJlc3RhdXJhbnRzIGluIGRpZmZlcmVudCBwcmljZSByYW5nZXMgYWNyb3NzIHRoZSBjaXR5DQoNCnllbHBfY2l0aWVzIDwtIGZ1bmN0aW9uKGRhdGFzZXQsIGNpdHkxLCBsb25nMSwgbG9uZzIsIGxhdDEsIGxhdDIsIHRpdGxlbmFtZSwgY29sb3IxKSB7DQp5ZWxwX3RvMSA8LSBzdWJzZXQoZGF0YXNldCwgY2l0eSA9PSBjaXR5MSAmIGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNQcmljZVJhbmdlMiANCiAgICAgICAgICAgICAgICAhPSAiTkEiICYgaXNfb3BlbiA9PSAxICYgYXR0cmlidXRlcy5SZXN0YXVyYW50c1Rha2VPdXQgIT0gIk5BIg0KICAgICAgICAgICAgICAgICYgYXR0cmlidXRlcy5SZXN0YXVyYW50c0RlbGl2ZXJ5ICE9ICJOQSIgJiANCiAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzVGFibGVTZXJ2aWNlICE9ICJOQSIgDQogICAgICAgICAgICAgICAgJiBhdHRyaWJ1dGVzLk5vaXNlTGV2ZWwgIT0gIk5BIiApDQoNCnNiYm94IDwtIG1ha2VfYmJveChsb24gPSB5ZWxwX3RvMSRsb25naXR1ZGUsIGxhdCA9IHllbHBfdG8xJGxhdGl0dWRlLCBmID0gMC4wMSkgDQp0b19tYXAgPC0gZ2V0X21hcChsb2NhdGlvbiA9IHNiYm94LCBtYXB0eXBlID0gInJvYWRtYXAiLCBzY2FsZSA9IDIsIA0KICAgICAgICAgICAgICAgICAgY29sb3I9ImJ3Iiwgem9vbSA9IDEwKQ0KDQpnZ21hcCh0b19tYXApICsNCiAgZ2VvbV9wb2ludChkYXRhPXllbHBfdG8xLCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlKSwgY29sb3IgPSBjb2xvcjEsDQpzaXplID0gMS41LCBhbHBoYSA9IDAuMSkgKyBzY2FsZV94X2NvbnRpbnVvdXMobGltID0gYyhsb25nMSwgbG9uZzIpKSArDQogIHNjYWxlX3lfY29udGludW91cyhsaW0gPSBjKGxhdDEsIGxhdDIpKSArICB4bGFiKCdMb25naXR1ZGUnKSArDQogIHlsYWIoJ0xhdGl0dWRlJykgKw0KICBnZ3RpdGxlKHRpdGxlbmFtZSkgKw0KICBndWlkZXMoY29sb3I9RkFMU0UpICsgDQogIGZhY2V0X3dyYXAofiBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIgLCBucm93ID0gMikrIA0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgIA0KfQ0KDQp5ZWxwX2NpdGllcyh5ZWxwX2ZsYXQxLCAiVG9yb250byIsIC03OS42LCAtNzkuMiwgNDMuNTgsIDQzLjgxLCANCiAgICAiTG9jYXRpb24gb2YgcmVzdGF1cmFudHMgaW4gVG9yb250byBieSBwcmljZSByYW5nZSAoMS00KSIsICIjNzU2YmIxIikNCg0KYGBgDQoNClJlc3RhdXJhbnRzIHdoaWNoIGFyZSBpbiB0aGUgYXZlcmFnZSAoMikgcHJpY2UgcmFuZ2UgYXJlIGZvdW5kIGV2ZXJ5d2hlcmUgdGhyb3VnaG91dCBUb3JvbnRvLCBhbmQgY29ycmVzcG9uZHMgYWxtb3N0IHByZWNpc2VseSB3aXRoIHRoZSBlYXJsaWVyIG1hcCBzaG93aW5nIHJlc3RhdXJhbnRzIGFjcm9zcyBUb3JvbnRvLiBIb3dldmVyLCBpbmV4cGVuc2l2ZSAoMSkgcHJpY2UgcmFuZ2UgcmVzdGF1cmFudHMgYXJlIG1haW5seSBjb25jZW50cmF0ZWQgaW4gdGhlIGRvd250b3duIGNvcmUgYW5kIGluIHRoZSBub3J0aC1jZW50cmFsIHBhcnQgb2YgdGhlIGNpdHkuIE90aGVyIHBhcnRzIG9mIHRoZSBjaXR5IChlc3BlY2lhbGx5IGp1c3QgYWJvdmUgdGhlIGRvd250b3duIGFyZWEpIGhhZCBmYXIgZmV3ZXIgaW5leHBlbnNpdmUgcmVzdGF1cmFudHMgdGhhbiBpbiB0aGUgZG93bnRvd24gY29yZSBhbmQgdGhlIG5vcnRoLWNlbnRyYWwgZW5kIGFsb25nIFlvbmdlIFN0cmVldC4gDQoNClRoZSByZXN0YXVyYW50cyBpbiB0aGUgIG1vcmUgZXhwZW5zaXZlICgzKSBwcmljZSByYW5nZSB3ZXJlIG9uY2UgYWdhaW4gY29uY2VudHJhdGVkIGluIHRoZSBkb3dudG93biBjb3JlLCBidXQgd2VyZSBhbHNvIHByZXZhbGVudCBnb2luZyBub3J0aCBhbG9uZyBZb25nZSBzdHJlZXQgKHRoZSBtYWluIHRob3JvdWdoZmFyZSB0aGF0IHJ1bnMgZG93biB0aGUgY2VudHJlIG9mIHRoZSBjaXR5KS4gVGhlIHByaWNpZXN0IHJlc3RhdXJhbnRzICg0KSB3ZXJlIG9ubHkgdG8gYmUgZm91bmQgYWxtb3N0IGV4Y2x1c2l2ZWx5IGFsb25nIFlvbmdlIHN0cmVldCBzdHJldGNoaW5nIGZyb20gdGhlIHdhdGVyZnJvbnQgbGFrZSBhcmVhIHVwIHRvIGFyb3VuZCBId3kgNDAxIGluIHRoZSBub3J0aC1jZW50cmFsIGVuZCBvZiB0aGUgY2l0eS4NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCg0KeWVscF9jaXRpZXMoeWVscF9mbGF0MSwgIk1vbnRy6WFsIiwgLTczLjc2LCAtNzMuNTIsIDQ1LjQyLCA0NS42LCANCiAgICAgICAgICAgICJMb2NhdGlvbiBvZiByZXN0YXVyYW50cyBpbiBNb250cmVhbCIsICIjNzU2YmIxIikNCmBgYA0KDQpJdCBzZWVtcyB0aGF0IHRoZSBtb3JlIGV4cGVuc2l2ZSByZXN0YXVyYW50cyBpbiB0aGUgMyByYW5nZSBhcmUgYWxtb3N0IGFzIHByZXZhbGVudCBhcyB0aG9zZSBpbiB0aGUgMSBwcmljZSByYW5nZSwgd2hpbGUgdGhvc2UgaW4gdGhlIG1vc3QgZXhwZW5zaXZlIHByaWNlIGNhdGVnb3J5IDQgYXJlIGFjdHVhbGx5IHF1aXRlIHZpc2libGUgaW4gdGhlIGRvd250b3duIGNvcmUuIFRoZSBnZW9ncmFwaGljIGNvbmNlbnRyYXRpb24gb2YgbW9yZSBleHBlbnNpdmUgcmVzdGF1cmFudHMgaW4gYSBwYXJ0aWN1bGFyIGxvY2FsZSBpcyBkZWZpbml0ZWx5IGhpZ2hlciB0aGFuIGluIFRvcm9udG8uDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQp5ZWxwX2NpdGllcyh5ZWxwX2ZsYXQxLCAiUGhvZW5peCIsIC0xMTIuMjM1LCAtMTExLjksIDMzLjM5NSwgMzMuNjMsIA0KICAgICAgICAiTG9jYXRpb24gb2YgcmVzdGF1cmFudHMgaW4gUGhvZW5peCBieSBwcmljZSByYW5nZSAoMS00KSIsICIjNzU2YmIxIikNCmBgYA0KDQpSZXN0YXVyYW50cyBpbiB0aGUgMSBwcmljZSByYW5nZSBhcmUgZm91bmQgZXZlcnl3aGVyZSBpbiBQaG9lbml4IGFzIGluIHRoZSBvcmlnaW5hbCBQaG9lbml4IG1hcCB3aXRoIGFsbCByZXN0YXVyYW50cyBhY3Jvc3MgcHJpY2UgcmFuZ2VzIHNob3duLiBBdmVyYWdlIHJlc3RhdXJhbnRzIGluIHRoZSAyIHByaWNlIHJhbmdlIHdlcmUgbGVzcyBudW1lcm91cyBhbmQgd2VyZSBtYWlubHkgY29uY2VudHJhdGVkIGluIHRoZSBkb3dudG93biBjb3JlIGFuZCB0aGUgbm9ydGhlcm4gcGFydCBvZiB0aGUgY2l0eS4gDQpPbiB0aGUgb3RoZXIgaGFuZCwgb3RoZXIgdGhhbiBhIHNtYWxsZXIgY2x1c3RlciBpbiB0aGUgY2l0eSBjZW50cmUgYW5kIGEgZmV3IHJlc3RhdXJhbnRzIHNwcmVhZCBvdXQgaW4gdGhlIG5vcnRoZWFzdGVybiBwYXJ0IG9mIHRoZSBjaXR5LCB0aGUgbW9yZSBleHBlbnNpdmUgcmVzdGF1cmFudHMgaW4gdGhlIDMgcHJpY2UgcmFuZ2Ugd2VyZSBub24tZXhpc3RlbnQuIFRoZSBwcmljaWVzdCAoNCkgcmVzdGF1cmFudHMgYXJlIGZvdW5kIHNjYXR0ZXJlZCB0aHJvdWdob3V0IHRoZSBjaXR5IGFuZCBudW1iZXIgbm8gbW9yZSB0aGFuIDIwLg0KDQpBdCBsZWFzdCBjb21wYXJlZCB0byBUb3JvbnRvIGFuZCBNb250cmVhbCwgdGhlcmUgd2VyZSBmZXdlciBwcmljZXkgcmVzdGF1cmFudHMgcmVsYXRpdmUgdG8gdGhlIHRvdGFsIG51bWJlci4gVGhpcyBraW5kIG9mIG1ha2VzIHNlbnNlLCBhcyB3ZSBzYXcgZWFybGllciB0aGF0IGJ5IGNvbXBhcmluZyBwZXJjZW50YWdlIG9mIHJlc3RhdXJhbnRzIGJ5IHByaWNlIHJhbmdlLCBPbnRhcmlvICh3aGVyZSBUb3JvbnRvIGlzIGxvY2F0ZWQpIGFuZCBRdWViZWMgKHdoZXJlIE1vbnRyZWFsIGlzIGxvY2F0ZWQpIGhhZCBmYXIgbW9yZSByZXN0YXVyYW50cyBpbiB0aGUgMy00IHByaWNlIHJhbmdlIHRoYW4gaW4gQXJpem9uYSAoV2hlcmUgUGhvZW5peCBpcyBsb2NhdGVkKS4NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCg0KeWVscF9jaXRpZXMoeWVscF9mbGF0MSwgIlNjb3R0c2RhbGUiLCAtMTEyLCAtMTExLjg1LCAzMy40NCwgMzMuNiwgDQogICAgICAgICAgICAiTG9jYXRpb24gb2YgcmVzdGF1cmFudHMgaW4gU2NvdHRzZGFsZSBieSBwcmljZSByYW5nZSIsICIjNzU2YmIxIikNCmBgYA0KDQpXaGlsZSB0aGUgMS0yIHByaWNlIHJhbmdlIHJlc3RhdXJhbnRzIGRvbWluYXRlZCAoYXMgYWx3YXlzKSwgdGhlcmUgd2VyZSBhY3R1YWxseSB0d28gY2x1c3RlcnMgb2YgcmVzdGF1cmFudHMgaW4gdGhlIG1vcmUgZXhwZW5zaXZlICgzKSBwcmljZSByYW5nZSBpbiBTY290dHNkYWxlIGNvbmNlbnRyYXRlZCBpbiBkb3dudG93biBTY290dHNkYWxlIGFuZCBpbiBQYXJhZGlzZSBWYWxsZXkgYWxvbmcgU2NvdHRzZGFsZSBSb2FkLiBTaW5jZSBib3RoIFRlbXBlIGFuZCBNZXNhICh0byB0aGUgc291dGhlYXN0IG9mIFBob2VuaXgpIGhhZCBzaW1pbGFyIHByaWNlIHJhbmdlcyBmb3IgaXRzIHJlc3RhdXJhbnRzLCB0aGlzIHN1Z2dlc3RzIHRoYXQgdGhlIG1vcmUgZXhwZW5zaXZlIHJlc3RhdXJhbnRzIGluIHRoZSBQaG9lbml4IG1ldHJvcG9saXRhbiBhcmVhIGFyZSBmb3VuZCBpbiBTY290dHNkYWxlLiANCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCg0KeWVscF9jaXRpZXNfc3RhcnM8LSBmdW5jdGlvbihkYXRhc2V0LCBjaXR5MSwgbG9uZzEsIGxvbmcyLCBsYXQxLCBsYXQyLCB0aXRsZW5hbWUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IxKSB7DQp5ZWxwX3RvMSA8LSBzdWJzZXQoZGF0YXNldCwgY2l0eSA9PSBjaXR5MSAmIGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNQcmljZVJhbmdlMiANCiAgICAgICAgICAgICAgICAhPSAiTkEiICYgaXNfb3BlbiA9PSAxICYgYXR0cmlidXRlcy5SZXN0YXVyYW50c1Rha2VPdXQgIT0gIk5BIg0KICAgICAgICAgICAgICAgICYgYXR0cmlidXRlcy5SZXN0YXVyYW50c0RlbGl2ZXJ5ICE9ICJOQSIgJiANCiAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzVGFibGVTZXJ2aWNlICE9ICJOQSIgDQogICAgICAgICAgICAgICAgJiBhdHRyaWJ1dGVzLk5vaXNlTGV2ZWwgIT0gIk5BIiApDQoNCnNiYm94IDwtIG1ha2VfYmJveChsb24gPSB5ZWxwX3RvMSRsb25naXR1ZGUsIGxhdCA9IHllbHBfdG8xJGxhdGl0dWRlLCBmID0gMC4wMSkgDQp0b19tYXAgPC0gZ2V0X21hcChsb2NhdGlvbiA9IHNiYm94LCBtYXB0eXBlID0gInJvYWRtYXAiLCBzY2FsZSA9IDIsIA0KICAgICAgICAgICAgICAgICAgY29sb3I9ImJ3Iiwgem9vbSA9IDEwKQ0KDQpnZ21hcCh0b19tYXApICsNCiAgZ2VvbV9wb2ludChkYXRhPXllbHBfdG8xLCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlKSwgY29sb3IgPSBjb2xvcjEsDQpzaXplID0gMS41LCBhbHBoYSA9IDAuMSkgKyBzY2FsZV94X2NvbnRpbnVvdXMobGltID0gYyhsb25nMSwgbG9uZzIpKSArDQogIHNjYWxlX3lfY29udGludW91cyhsaW0gPSBjKGxhdDEsIGxhdDIpKSArICB4bGFiKCdMb25naXR1ZGUnKSArDQogIHlsYWIoJ0xhdGl0dWRlJykgKw0KICBnZ3RpdGxlKHRpdGxlbmFtZSkgKw0KICBndWlkZXMoY29sb3I9RkFMU0UpICsgDQogIGZhY2V0X3dyYXAofiBzdGFycyAsIG5yb3cgPSAzKSsgDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSAgDQp9DQoNCnllbHBfY2l0aWVzX3N0YXJzKHllbHBfZmxhdDEsICJUb3JvbnRvIiwgLTc5LjYsIC03OS4yLCA0My41OCwgNDMuODEsIA0KICAgICJMb2NhdGlvbiBvZiByZXN0YXVyYW50cyBpbiBUb3JvbnRvIGJ5IFllbHAgc3RhcnMiLCAiIzJiOGNiZSIpDQoNCmBgYA0KDQpJIGNvbmNsdWRlIHRoZSBiaXZhcmlhdGUgcGxvdHMgc2VjdGlvbiB3aXRoIGEgcXVpY2sgbG9vayBhdCBob3cgZ2VvZ3JhcGhpYyBjb25jZW50cmF0aW9uIG9mIHJlc3RhdXJhbnRzIHZhcnkgYnkgWWVscCBzdGFycy4gDQoNCkJlY2F1c2Ugb2YgdGhlIGxhcmdlIG51bWJlciBvZiByZXN0YXVyYW50cyBpbiB0aGUgMyB0byA0IHN0YXIgcmFuZ2UsIHRoZXJlIGlzIG5vdCBtdWNoIHRvIGJlIHNhaWQgaGVyZS4gSG93ZXZlciwgYXQgdGhlIGV4dHJlbWVzLCAxIHN0YXIgYW5kIDUgc3RhciwgdGhlcmUgc2VlbSB0byBiZSBzb21lIGRlZ3JlZSBvZiBnZW9ncmFwaGljIGNvbmNlbnRyYXRpb24gdGhhdCBkaWZmZXJzIGZyb20gdGhlIG90aGVyIHN0YXIgcmFuZ2VzLiBSZXN0YXVyYW50cyByYXRlZCAxIGFuZCAxLjUgdGVuZCB0byBiZSBtb3JlIHByZXZhbGVudCBpbiB0aGUgbm9ydGh3ZXN0ZXJuIHBhcnQgb2YgdGhlIGNpdHksIHdoaWxlIHJlc3RhdXJhbnRzIHJhdGVkIDUgdGVuZCB0byBiZSBsb2NhdGVkIGp1c3QgdG8gdGhlIHdlc3Qgb2YgdGhlIGRvd250b3duIGNvcmUuDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQp5ZWxwX2NpdGllc19zdGFycyh5ZWxwX2ZsYXQxLCAiUGhvZW5peCIsIC0xMTIuMjM1LCAtMTExLjksIDMzLjM5NSwgMzMuNjMsIA0KICAgICAgICAiTG9jYXRpb24gb2YgcmVzdGF1cmFudHMgaW4gUGhvZW5peCBieSBzdGFycyIsICIjMmI4Y2JlIikNCmBgYA0KDQpJbiBQaG9lbml4LCB3aGF0IHdlIGNhbiBzZWUgaW1tZWRpYXRlbHkgaXMgdGhhdCB0aGUgcmVzdGF1cmFudHMgcmF0ZWQgYmV0d2VlbiAxIHRvIDEuNSBzdGFycyBhcmUgbW9zdCBsaWtlbHkgaW4gdGhlIHdlc3Rlcm4gaGFsZiAoc3VidXJiYW4pIG9mIHRoZSBjaXR5LCBidXQgZm9yIGFsbCBvdGhlciBZZWxwIHN0YXJzLCByZXN0YXVyYW50cyBjb3VsZCBiZSBmb3VuZCBhbGwgb3ZlciB0aGUgY2l0eS4NCg0KU28gZmFyLCB0aGlzIGdlb2dyYXBoaWNhbCBhbmFseXNpcyBvZiB0aGUgbG9jYXRpb24gb2YgcmVzdGF1cmFudHMgaW4gdGhlc2UgY2l0aWVzIGhhcyBiZWVuIGludGVyZXN0aW5nLiBNb3JlIHdpbGwgYmUgZGlzY3Vzc2VkIHVzaW5nIGEgZ3JlYXRlciBudW1iZXIgb2YgdmFyaWFibGVzIGxhdGVyIG9uLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQoNCg0KeWVscF9jaXRpZXMxIDwtIGZ1bmN0aW9uKGRhdGFzZXQsIGNpdHkxLCBsb25nMSwgbG9uZzIsIGxhdDEsIGxhdDIsIHRpdGxlbmFtZSkgew0KICANCiAgeWVscF90bzEgPC0gc3Vic2V0KHllbHBfZmxhdDEsIGNpdHkgPT0gY2l0eTEgJiANCiAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNQcmljZVJhbmdlMiAhPSAiTkEiICYgaXNfb3BlbiAhPSAiTkEiIA0KICAgICAgICAgICAgICAgICAgJiBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzVGFrZU91dCAhPSAiTkEiICYgDQogICAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzRGVsaXZlcnkgIT0gIk5BIiAmICAgICAgICANCiAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNUYWJsZVNlcnZpY2UgIT0gIk5BIikNCiAgDQp5ZWxwX3RvMiA8LSBzdWJzZXQoeWVscF90bzEsICFpcy5uYShhdHRyaWJ1dGVzLkFsY29ob2wpKQ0Kc2Jib3ggPC0gbWFrZV9iYm94KGxvbiA9IHllbHBfdG8yJGxvbmdpdHVkZSwgbGF0ID0geWVscF90bzIkbGF0aXR1ZGUsIGYgPSAwLjAxKSANCnRvX21hcCA8LSBnZXRfbWFwKGxvY2F0aW9uID0gc2Jib3gsIG1hcHR5cGUgPSAicm9hZG1hcCIsIHNjYWxlID0gMiwgDQogICAgICAgICAgICAgICAgICBjb2xvcj0iYnciLCB6b29tID0gMTApDQogIA0KZ2dtYXAodG9fbWFwKSArDQogIGdlb21fcG9pbnQoZGF0YT15ZWxwX3RvMiwgYWVzKHggPSBsb25naXR1ZGUsIHkgPSBsYXRpdHVkZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gYXR0cmlidXRlcy5BbGNvaG9sKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSwgYWxwaGEgPSAwLjMpICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX3hfY29udGludW91cyhsaW0gPSBjKGxvbmcxLCBsb25nMikpICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX3lfY29udGludW91cyhsaW0gPSBjKGxhdDEsIGxhdDIpKSArICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeGxhYignTG9uZ2l0dWRlJykgKyB5bGFiKCdMYXRpdHVkZScpICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdndGl0bGUodGl0bGVuYW1lKSArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9kaXNjcmV0ZShuYW1lPSJBbGNvaG9sIHNlcnZpY2UiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiYmVlcit3aW5lIiwgImZ1bGxfYmFyIiwgIm5vbmUiKSkgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICANCn0NCg0KeWVscF9jaXRpZXMxKHllbHBfZmxhdDEsICJUb3JvbnRvIiwgLTc5LjYsIC03OS4yLCA0My41OCwgNDMuODEsIA0KICAgICAgICAgICAgICJMb2NhdGlvbiBvZiByZXN0YXVyYW50cyBpbiBUb3JvbnRvIikNCmBgYA0KDQoNCiMgQml2YXJpYXRlIEFuYWx5c2lzDQoNCiMjIyBUYWxrIGFib3V0IHNvbWUgb2YgdGhlIHJlbGF0aW9uc2hpcHMgeW91IG9ic2VydmVkIGluIHRoaXMgcGFydCBvZiB0aGUgaW52ZXN0aWdhdGlvbi4gSG93IGRpZCB0aGUgZmVhdHVyZShzKSBvZiBpbnRlcmVzdCB2YXJ5IHdpdGggb3RoZXIgZmVhdHVyZXMgaW4gdGhlIGRhdGFzZXQ/DQoNCjEpIE1vcmUgZXhwZW5zaXZlIHJlc3RhdXJhbnRzIGluIGhpZ2hlciBwcmljZSByYW5nZXMgdGVuZCB0byBiZSByYXRlZCBtb3JlIGhpZ2hseSwgaG93ZXZlciB0aGUgcGVyY2VudGFnZSBvZiB2YXJpYW5jZSBleHBsYWluZWQgYnkgdGhlIGVmZmVjdCBvZiBwcmljZSBvbiBzdGFycyBpcyBuZWdsaWdpYmxlIGluZGljYXRpbmcgdGhhdCB0aGVyZSBhcmUgbW9zdCBsaWtlbHkgbWFueSBvdGhlciBmYWN0b3JzIHRoYXQgZXhwbGFpbiB0aGUgYXZlcmFnZSBZZWxwIHN0YXIgcmF0aW5nIHRoYXQgYSByZXN0YXVyYW50IHJlY2VpdmVzLg0KDQoyKSBUaGUgcmV2aWV3IGNvdW50IG9mIGFsbCBZZWxwLXJhdGVkIGVzdGFibGlzaG1lbnRzIGlzIGRpc3Byb3BvcnRpb25hdGVseSByZXByZXNlbnRlZCBieSBOZXZhZGEgYW5kIEFyaXpvbmEsIHdpdGggTmV2YWRhIGhhdmluZyBhIG11Y2ggaGlnaGVyIGF2ZXJhZ2UgbnVtYmVyIG9mIHJldmlld3MgZm9yIGl0cyBlc3RhYmxpc2htZW50cyBjb21wYXJlZCB3aXRoIHRoZSBvdGhlciA4IHN0YXRlcyBpbiB0aGUgZGF0YSBzZXQuDQoNCjMpIFRoZSBDYW5hZGlhbiBwcm92aW5jZXMgb2YgUXVlYmVjIGFuZCBPbnRhcmlvIGFsb25nIHdpdGggaXRzIG1ham9yIGNpdGllcyBUb3JvbnRvIGFuZCBNb250cmVhbCBoYWQgdGhlIGhpZ2hlc3QgYXZlcmFnZSBwcmljZSByYW5nZXMgZm9yIGl0cyByZXN0YXVyYW50cywgd2hpbGUgQXJpem9uYSBhbG9uZyB3aXRoIGl0cyBtYWpvciBjaXRpZXMgb2YgdGhlIFBob2VuaXggbWV0cm9wb2xpdGFuIGFyZWEgKFBob2VuaXgsIFRlbXBlLCBhbmQgTWVzYSkgaGFkIHRoZSBsb3dlc3QgYXZlcmFnZSBwcmljZSByYW5nZXMuDQoNCjQpIEluIHRlcm1zIG9mIHJhdGluZ3MsIFNjb3R0c2RhbGUgaW4gQVogYW5kIE1vbnRyZWFsIGluIFFDIGhhZCBoaWdoZXIgWWVscCBzdGFycyByYXRlZCBmb3IgaXRzIHJlc3RhdXJhbnRzIHRoYW4gb3RoZXIgTm9ydGggQW1lcmljYW4gY2l0aWVzLg0KDQo1KSBJbiB0ZXJtcyBvZiBnZXR0aW5nIHRoZSBtb3N0IHZhbHVlIG91dCBvZiB5b3VyIGRvbGxhciBpbiBhIHJlc3RhdXJhbnQsIHRoZSBjaXRpZXMgb2YgdGhlIFBob2VuaXggbWV0cm9wb2xpdGFuIGFyZWEgKGV4Y2VwdCBTY290dHNkYWxlKSBzY29yZWQgdGhlIGhpZ2hlc3QgcmVsYXRpdmUgdG8gdGhlIG90aGVyIGNpdGllcy4NCg0KNikgQXJvdW5kIG9ubHkgMTAtMjUlIG9mIHJlc3RhdXJhbnRzIG9mZmVyIGEgZnVsbCBzdWl0ZSBvZiBkaW5pbmcgb3B0aW9ucyBzdWNoIGFzIGRlbGl2ZXJ5LCB0YWtlLW91dCBhbmQgdGFibGUgc2VydmljZSAoZGluZS1pbikuIFRoaXMgd2FzIG1haW5seSBkdWUgdG8gdGhlIHJlbGF0aXZlbHkgbG93IHBlcmNlbnRhZ2Ugb2YgcmVzdGF1cmFudHMgdGhhdCBkaWQgZGVsaXZlcnkuDQoNCjcpIFJlc3RhdXJhbnRzIGluIFRvcm9udG8gYW5kIG1vbnRyZWFsIGFyZSBjb25jZW50cmF0ZWQgbWFpbmx5IGluIHRoZSBkb3dudG93biBjb3JlLCB3aGlsZSBvdGhlciBjaXRpZXMgc3VjaCBhcyBQaG9lbml4IGhhZCBpdHMgcmVzdGF1cmFudHMgc3ByZWFkIG91dCBhY3Jvc3MgdGhlIGNpdHkuIA0KDQo4KSBXaGlsZSBtb3JlIGV4cGVuc2l2ZSByZXN0YXVyYW50cyAocHJpY2UgcmFuZ2UgMy00KSB3ZXJlIGZvdW5kIGluIHRoZSBzYW1lIHBsYWNlcyBhcyB3aGVyZSBpdHMgaGlnaGVzdCBjb25jZW50cmF0aW9uIHdhcyBpbiAodXN1YWxseSBkb3dudG93biBjb3JlKSwgdGhpcyB3YXMgbm90IG5lY2Vzc2FyaWx5IHRoZSBjYXNlIGluIHRoZSBQaG9lbml4IG1ldHJvcG9saXRhbiBhcmVhIChQaG9lbml4LCBTY290dHNkYWxlIGV0Yy4pLCB3aGVyZSBpdHMgbW9zdCBleHBlbnNpdmUgcmVzdGF1cmFudHMgd2VyZSBpbiBuZWFyYnkgU2NvdHRzZGFsZSwgd2l0aCB0aGUgUGhvZW5peCBkb3dudG93biBjb3JlIGJlaW5nIGFsbW9zdCBkZXZvaWQgb2YgcmVzdGF1cmFudHMgaW4gdGhlIDMtNCBwcmljZSByYW5nZS4gTW9yZSBleHBlbnNpdmUgaW4gdGhlIDMtNCBwcmljZSByYW5nZSB3ZXJlIHF1aXRlIHByZXZhbGVudCBpbiBNb250cmVhbCAoYWxtb3N0IGFzIG1hbnkgYXMgdGhvc2UgaW4gdGhlIDEgcHJpY2UgcmFuZ2UpIHRoYW4gY29tcGFyZWQgdG8gb3RoZXIgY2l0aWVzLg0KDQoNCiMjIyBEaWQgeW91IG9ic2VydmUgYW55IGludGVyZXN0aW5nIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiB0aGUgb3RoZXIgZmVhdHVyZXMgKG5vdCB0aGUgbWFpbiBmZWF0dXJlKHMpIG9mIGludGVyZXN0KT8NCg0KMSkgUmVzdGF1cmFudHMgd2l0aCBsb3dlciBub2lzZSBsZXZlbHMgKHF1aWV0KSB0ZW5kIHRvIGhhdmUgaGlnaGVyIHJhdGluZ3MgYXMgd2VsbCwgdGhvdWdoIGZvciB0aGUgc2FtZSByZWFzb25zIGFzIHByaWNlIHJhbmdlLCB0aGlzIGVmZmVjdCAob24gaXRzIG93bikgaXMgbmVnbGlnaWJsZS4NCg0KMikgVmVyeSBmZXcgcmVzdGF1cmFudHMgcmVxdWlyZWQgZm9ybWFsIG9yIGRyZXNzeSBhdHRpcmUsIHRob3VnaCBRdWViZWMgc2VlbWVkIHRvIHNjb3JlIGp1c3Qgc2xpZ2h0bHkgaGlnaGVyIHJlbGF0aXZlIHRvIG90aGVyIHN0YXRlcy4NCg0KDQojIyMgV2hhdCB3YXMgdGhlIHN0cm9uZ2VzdCByZWxhdGlvbnNoaXAgeW91IGZvdW5kPw0KDQpJbiB0ZXJtcyBvZiBteSBnZW9ncmFwaGljIGFuYWx5c2lzIG9mIHRoZSA0IGNpdGllcyBhYm92ZSwgdGhlIHN0cm9uZ2VzdCByZWxhdGlvbnNoaXAgdGhhdCBJIGZvdW5kIHdhcyB0aGF0IGFsbCByZXN0YXVyYW50cyByZWdhcmRsZXNzIG9mIHByaWNlIHJhbmdlIHdlcmUgYWxtb3N0IGFsd2F5cyBjb25jZW50cmF0ZWQgaW4gdGhlIGRvd250b3duIGNvcmUgb3IgaW4gc29tZSBuYXJyb3cgc3RyaXAgb3V0c2lkZSBvZiBhIGNlbnRyYWwgYXJlYS4gDQoNCg0KDQojIE11bHRpdmFyaWF0ZSBQbG90cyBTZWN0aW9uDQoNCk1vdmluZyBvbiBmcm9tIGxvb2tpbmcgYXQgcHJpY2UgcmFuZ2VzLCBsZXQgdXMgbm93IGV4cGxvcmUgdGhlIGdlb2dyYXBoaWNhbCBkaXN0cmlidXRpb24gb2YgYWxjb2hvbCBzZXJ2aWNlIGFjcm9zcyByZXN0YXVyYW50cyBpbiBUb3JvbnRvLiBUaGUgbWFwIGFib3ZlIHNob3dzIHRoYXQgbW9zdCBmdWxsIGJhciBzZXJ2aWNlcyBhcmUgY29uY2VudHJhdGVkIGRvd250b3duLCB0aG91Z2ggdGhlcmUgaXMgYSBsYXJnZSBhcmVhIGluIHRoZSB2ZXJ5IGNlbnRyZSBvZiB0aGUgZG93bnRvd24gY29yZSBpbiB3aGljaCBlaXRoZXIgbm8gYWxjb2hvbCBpcyBwcm92aWRlZCBvciBvbmx5IGJlZXIgYW5kIHdpbmUgaXMuIE1vc3QgcGxhY2VzIHRvIHRoZSBub3J0aHdlc3QgYW5kIG5vcnRoZWFzdCBvZiB0aGUgZG93bnRvd24gY2x1c3RlciBvZiByZXN0YXVyYW50cyBpbiB0aGUgbWlkZGxlIGFsc28gZGlkIG5vdCBwcm92aWRlIGFsY29ob2wgc2VydmljZXMgZWl0aGVyLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KeWVscF9jaXRpZXMxKHllbHBfZmxhdDEsICJQaG9lbml4IiwgLTExMi4yMzUsIC0xMTEuOSwgMzMuMzk1LCAzMy42MywgDQogICAgICAgICAgICAgIkxvY2F0aW9uIG9mIHJlc3RhdXJhbnRzIGluIFBob2VuaXgiKQ0KYGBgDQoNCkluIFBob2VuaXgsIGl0IHNlZW1zIHRoYXQgYWxjb2hvbCBpcyBvZmZlcmVkIGluIGZld2VyIHJlc3RhdXJhbnRzIHRoYW4gd2FzIHRoZSBjYXNlIGluIFRvcm9udG8sIGFuZCBpdCBpcyBjbGVhciBmcm9tIHRoZSBtYXAgYWJvdmUgdGhhdCBtb3N0IHJlc3R1cmFudHMgdG8gdGhlIHNvdXRoIGFuZCB3ZXN0IG9mIGludGVyc3RhdGUgZGlkIG5vdCBvZmZlciBhIGZ1bGwgYmFyLiBFdmVuIHdpdGhpbiB0aGUgY2VudHJlIG9mIFBob2VuaXgsIHRoZXJlIGV4aXN0IGxhcmdlIGFyZWFzIHRoYXQgZG8gbm90IG9mZmVyIGFsY29ob2wgb3Igb25seSBvZmZlciBiZWVyIGFuZCB3aW5lLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KeWVscF9jaXRpZXMxKHllbHBfZmxhdDEsICJNb250culhbCIsIC03My43NiwgLTczLjUyLCA0NS40MiwgNDUuNiwgDQogICAgICAgICAgICAgIkxvY2F0aW9uIG9mIHJlc3RhdXJhbnRzIGluIE1vbnRyZWFsIikNCg0KYGBgDQoNCkluIE1vbnRyZWFsLCBpdCBpcyBtdWNoIGhhcmRlciB0byB0ZWxsIHdoZXJlIHRoZSBnZW9ncmFwaGljIGNvbmNlbnRyYXRpb24gb2YgYWxjb2hvbCBzZXJ2aWNlIGlzIHdpdGhpbiByZXN0YXVyYW50cyB0aHJvdWdob3V0IHRoZSBjaXR5LiBJdCBzZWVtcyBsaWtlIGEgbWFzc2l2ZSBjb25jZW50cmF0aW9uIG9mIGZ1bGwgYmFyIHNlcnZpY2VzIGluIHRoZSBkb3dudG93biBjb3JlLCB3aXRoIGFuIGV2ZW4gbWl4IG9mIGFsY29ob2wgc2VydmljZSBsZXZlbHMgYmVpbmcgcHJvdmlkZWQgYnkgcmVzdGF1cmFudHMgaW4gdGhlIHBlcmlwaGVyYWwgYXJlYXMgb2YgdGhlIGNpdHkuDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQp5ZWxwX2NpdGllczIgPC0gZnVuY3Rpb24oZGF0YXNldCwgY2l0eTEsIGxvbmcxLCBsb25nMiwgbGF0MSwgbGF0MiwgdGl0bGVuYW1lKSB7DQoNCnllbHBfdG8xIDwtIHN1YnNldCh5ZWxwX2ZsYXQxLCBjaXR5ID09IGNpdHkxICYgDQogICAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIgIT0gIk5BIiAmIGlzX29wZW4gIT0gIk5BIiAmIA0KICAgICAgICAgICAgICAgICAgYXR0cmlidXRlcy5SZXN0YXVyYW50c1Rha2VPdXQgIT0gIk5BIiAmIA0KICAgICAgICAgICAgICAgICAgYXR0cmlidXRlcy5SZXN0YXVyYW50c0RlbGl2ZXJ5ICE9ICJOQSIgJiAgICAgICAgDQogICAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzVGFibGVTZXJ2aWNlICE9ICJOQSIpDQoNCnllbHBfdG8yIDwtIHN1YnNldCh5ZWxwX3RvMSwgIWlzLm5hKGF0dHJpYnV0ZXMuTm9pc2VMZXZlbCkpDQpzYmJveCA8LSBtYWtlX2Jib3gobG9uID0geWVscF90bzEkbG9uZ2l0dWRlLCBsYXQgPSB5ZWxwX3RvMSRsYXRpdHVkZSwgZiA9IDAuMDEpIA0KdG9fbWFwIDwtIGdldF9tYXAobG9jYXRpb24gPSBzYmJveCwgbWFwdHlwZSA9ICJyb2FkbWFwIiwgc2NhbGUgPSAyLCANCiAgICAgICAgICAgICAgICAgIGNvbG9yPSJidyIsIHpvb20gPSAxMCkNCg0KZ2dtYXAodG9fbWFwKSArDQogIGdlb21fcG9pbnQoZGF0YT15ZWxwX3RvMiwgYWVzKHggPSBsb25naXR1ZGUsIHkgPSBsYXRpdHVkZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gYXR0cmlidXRlcy5Ob2lzZUxldmVsKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMS41LCBhbHBoYSA9IDAuMykgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV94X2NvbnRpbnVvdXMobGltID0gYyhsb25nMSwgbG9uZzIpKSArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX3lfY29udGludW91cyhsaW0gPSBjKGxhdDEsIGxhdDIpKSArICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB4bGFiKCdMb25naXR1ZGUnKSArIHlsYWIoJ0xhdGl0dWRlJykgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZ3RpdGxlKHRpdGxlbmFtZSkgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV9jb2xvcl9kaXNjcmV0ZShuYW1lPSJOb2lzZSBsZXZlbHMiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiYXZlcmFnZSIsICJsb3VkIiwgInF1aWV0IiwgInZlcnkgbG91ZCIpKSANCn0NCnllbHBfY2l0aWVzMih5ZWxwX2ZsYXQxLCAiVG9yb250byIsIC03OS42LCAtNzkuMiwgNDMuNTgsIDQzLjgxLCANCiAgICAgICAgICAgICAiTG9jYXRpb24gb2YgcmVzdGF1cmFudHMgaW4gVG9yb250byIpDQpgYGANCg0KTmV4dCB1cCwgSSB3YW50ZWQgdG8gc2VlIGlmIG5vaXNlIGxldmVscyBkaWZmZXJlZCBiZXR3ZWVuIGRpZmZlcmVudCBkb3dudG93biBhbmQgc3VidXJiYW4gYXJlYXMgb2YgVG9yb250by4gSW4gb3VyIHByZXZpb3VzIGFuYWx5c2lzIG9mIG5vaXNlIGxldmVscywgd2Ugc2F3IHRoYXQgdHdvLXRoaXJkcyBvZiByZXN0YXVyYW50cyB3ZXJlIGF2ZXJhZ2UgaW4gdGVybXMgb2Ygbm9pc2UgbGV2ZWxzLCBzbyBpdCBpcyBub3Qgc3VycHJpc2luZyB0byBzZWUgYXZlcmFnZSBub2lzZSBsZXZlbHMgKGluIHJlZCkgZG9taW5hdGUgdGhyb3VnaG91dCB0aGUgY2l0eS4gVGhlIHJlc3RhdXJhbnRzIGluIHRoZSBzb3V0aGVhc3Rlcm4gYW5kIG5vcnRod2VzdGVybiBwYXJ0cyBvZiB0aGUgY2l0eSBzZWVtIGJlIG1haW5seSBhdmVyYWdlIG9yIHF1aWV0LiBUaGUgcmVzdCBvZiB0aGUgY2l0eSwgaG93ZXZlciwgc2VlbXMgdG8gYmUgc3ByaW5rbGVkIHF1aXRlIGV2ZW5seSB3aXRoIHJlc3RhdXJhbnRzIHdpdGggYWxsIHNvcnRzIG9mIG5vaXNlIGxldmVscy4NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnllbHBfY2l0aWVzMih5ZWxwX2ZsYXQxLCAiUGhvZW5peCIsIC0xMTIuMjMsIC0xMTEuOSwgMzMuMzksIDMzLjYzLCANCiAgICAgICAgICAgICAiTG9jYXRpb24gb2YgcmVzdGF1cmFudHMgaW4gUGhvZW5peCIpDQpgYGANCg0KSW4gdGhlIGNhc2Ugb2YgUGhvZW5peCwgcmVzdGF1cmFudHMgb2YgYWxsIG5vaXNlIGxldmVscyB3ZXJlIGV2ZW5seSBzcHJpbmtsZWQgdGhyb3VnaG91dCB0aGUgY2l0eS4gSXQgc2VlbXMgdGhlcmUgaXMgbGl0dGxlIHRvIG5vIGNvcnJlbGF0aW9uIGJldHdlZW4gcmVzdGF1cmFudCBub2lzZSBsZXZlbHMgYW5kIGdlb2dyYXBoaWMgZGlzcGVyc2lvbi4NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnllbHBfY2l0aWVzMih5ZWxwX2ZsYXQxLCAiTW9udHLpYWwiLCAtNzMuNzYsIC03My41MiwgNDUuNDIsIDQ1LjYsIA0KICAgICAgICAgICAgICJMb2NhdGlvbiBvZiByZXN0YXVyYW50cyBpbiBNb250cmVhbCIpDQpgYGANCg0KVW5saWsgUGhvZW5peCBhbmQgVG9yb250bywgTW9udHJlYWwgZG9lcyBoYXZlIGEgZmV3IGFyZWFzLCBwYXJ0aWN1bGFybHkgaW4gdGhlIGFyZWFzIHRvIHRoZSBub3J0aGVhc3QgYW5kIHNvdXRoIG9mIHRoZSBkb3dudG93biBjb3JlLCB0aGF0IGFyZSBhY3R1YWxseSBkb21pbmF0ZWQgZXhjbHVzaXZlbHkgYnkgYXZlcmFnZSBhbmQgcXVpZXQgcmVzdGF1cmFudHMuIEF0IGxlYXN0IGFtb25nIHRoZXNlIHRocmVlIGNpdGllcywgaW4gZ2VuZXJhbCwgcmVzdGF1cmFudHMgb2YgYWxsIG5vaXNlIGxldmVscyBzZWVtIHRvIGJlIHNwcmlua2xlZCB0aHJvdWdob3V0IHRoZSBjaXR5Lg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KeWVscF9jaXRpZXMzIDwtIGZ1bmN0aW9uKGRhdGFzZXQsIGNpdHkxLCBsb25nMSwgbG9uZzIsIGxhdDEsIGxhdDIsIHRpdGxlbmFtZSkgew0KDQp5ZWxwX21lYWxzIDwtIHN1YnNldChkYXRhc2V0LCBjaXR5ID09IGNpdHkxICYgDQogICAgICAgICAgICAgICAgICAgICFpcy5uYShhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIpICYNCiAgICAgICAgICAgICAgICAgICAgIWlzLm5hKGlzX29wZW4pICYgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNUYWtlT3V0KSAmIA0KICAgICAgICAgICAgICAgICAgICAhaXMubmEoYXR0cmlidXRlcy5SZXN0YXVyYW50c0RlbGl2ZXJ5KSAgJiANCiAgICAgICAgICAgICAgICAgICAgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNUYWJsZVNlcnZpY2UpICYNCiAgICAgICAgICAgICAgICAgICAgIWlzLm5hKGF0dHJpYnV0ZXMuR29vZEZvck1lYWwuZGlubmVyKSkNCg0Kc2Jib3ggPC0gbWFrZV9iYm94KGxvbiA9IHllbHBfbWVhbHMkbG9uZ2l0dWRlLCANCiAgICAgICAgICAgICAgICAgICBsYXQgPSB5ZWxwX21lYWxzJGxhdGl0dWRlLCBmID0gMC4wMSkgDQp0b19tYXAgPC0gZ2V0X21hcChsb2NhdGlvbiA9IHNiYm94LCBtYXB0eXBlID0gInJvYWRtYXAiLCBzY2FsZSA9IDIsIA0KICAgICAgICAgICAgICAgICAgY29sb3I9ImJ3Iiwgem9vbSA9IDEwKQ0KDQpnZ21hcCh0b19tYXApICsNCmdlb21fcG9pbnQoZGF0YT15ZWxwX21lYWxzLCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBhdHRyaWJ1dGVzLkdvb2RGb3JNZWFsLmRpbm5lciksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxLjUsIGFscGhhID0gMC4zKSArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV94X2NvbnRpbnVvdXMobGltID0gYyhsb25nMSwgbG9uZzIpKSArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltID0gYyhsYXQxLCBsYXQyKSkgKyAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhsYWIoJ0xvbmdpdHVkZScpICsgeWxhYignTGF0aXR1ZGUnKSArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZ3RpdGxlKHRpdGxlbmFtZSkgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfY29sb3JfZGlzY3JldGUobmFtZT0iR29vZCBmb3IgZGlubmVyIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIk5vdCBnb29kIiwgIkdvb2QiKSkgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICANCn0NCnllbHBfY2l0aWVzMyh5ZWxwX2ZsYXQxLCAiVG9yb250byIsIC03OS42LCAtNzkuMiwgNDMuNTgsIDQzLjgxLCANCiAgICAgICAgICAgICAiTG9jYXRpb24gb2YgcmVzdGF1cmFudHMgaW4gVG9yb250byIpDQpgYGANCg0KSW4gdGhlIG5leHQgZmV3IHBsb3RzLCBhcyBhIG1hdHRlciBvZiBwZXJzb25hbCBpbnRlcmVzdCwgSSBhbSBnb2luZyB0byBsb29rIGF0IHdoZXJlIHBsYWNlcyB0aGF0IGFyZSBnb29kIGZvciBnb2luZyBvdXQgZm9yIGRpbm5lciBhcmUgbG9jYXRlZCB3aXRoaW4gYSBjaXR5LiANCg0KSW4gVG9yb250bywgdGhlIGJlc3QgcGxhY2VzIHRvIGZpbmQgcmVzdGF1cmFudHMgdGhhdCBhcmUgZ29vZCBmb3IgZGlubmVyIGFyZSBpbiB0aGUgZG93bnRvd24gY29yZSBhbmQgYWxvbmcgWW9uZ2UgU3RyZWV0ICh0aGUgdmVydGljYWwgc3RyZWV0IHRocm91Z2ggdGhlIGNlbnRyZSBvZiB0aGUgY2l0eSB0aGF0J3MgZmlsbGVkIHdpdGggcmVzdGF1cmFudHMpLiBIb3dldmVyLCBpbiB0ZXJtcyBvZiB0aGUgcGVyY2VudGFnZSBvZiBwbGFjZXMgdGhhdCBhcmUgZm9yIGRpbm5lciwgdGhlIGNsdXN0ZXIgb2YgcmVzdGF1cmFudHMgaW4gdGhlIG5vcnRoZXJuIHBhcnQgb2YgdGhlIGNpdHkgYWxvbmcgWW9uZ2UgU3RyZWV0LCBhbmQgdGhlIGRvd250b3duIGFyZWEgY2xvc2UgdG8gdGhlIGxha2UgYnV0IGp1c3QgYWNyb3NzIGZyb20gdGhlIGlzbGFuZCBpbiB0aGUgc291dGhjZW50cmFsIHBhcnQgb2YgdGhlIGNpdHkgYXJlIHRoZSBiZXN0IHBsYWNlcyB0byBnbyBpZiBvbmUgd2FudGVkIHRvIGxvb2sgZXhjbHVzaXZlbHkgZm9yIGRpbm5lciBwbGFjZXMgd2hlbiBnb2luZyBvdXQgYXQgbmlnaHQuIE9uIHRoZSBvdGhlciBoYW5kLCB0aGUgbm9ydGh3ZXN0ZXJuIHBhcnQgb2YgVG9yb250byBzZWVtcyB0byBiZSBmYWlybHkgZGV2b2lkIG9mIHBsYWNlcyB0byBnbyBvdXQgdG8gZm9yIGRpbm5lci4NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnllbHBfY2l0aWVzMyh5ZWxwX2ZsYXQxLCAiUGhvZW5peCIsIC0xMTIuMjMsIC0xMTEuOSwgMzMuMzksIDMzLjYyLCANCiAgICAgICAgICAgICAiTG9jYXRpb24gb2YgcmVzdGF1cmFudHMgaW4gUGhvZW5peCIpDQpgYGANCg0KQ29tcGFyZWQgdG8gVG9yb250bywgaXQgc2VlbXMgdGhhdCBQaG9lbml4IGhhcyBhIG11Y2ggd2lkZXIgZ2VvZ3JhcGhpY2FsIGRpc3BlcnNpb24gb2YgcmVzdGF1cmFudHMgdGhhdCBhcmUgZm9yIGdvb2QgZm9yIGRpbm5lciBhcyBjb21wYXJlZCB0byBUb3JvbnRvLCB0aG91Z2ggdGhlIG5vcnRoIGNlbnRyYWwgYXJlYSBvZiB0aGUgY2l0eSBzZWVtcyB0byBoYXZlIGEgaGlnaGVyIGNvbmNlbnRyYXRpb24gdGhhbiB0aGUgc291dGhlcm4gYW5kIHdlc3Rlcm4gcGFydHMgb2YgdGhlIGNpdHkuDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCnJlc3RfY2l0eV9kaW5uZXJfY291bnQgPC0gcmVzdF9jaXR5X2Rpbm5lciAlPiUNCmdyb3VwX2J5KGNpdHkpJT4lDQpzdW1tYXJpc2UoZ29vZF9mb3JfZGlubmVyID0gc3VtKGRpbm5lcikpIA0KDQpyZXN0X2NpdHlfY291bnQgPC0gcmVzdF9jaXR5X2Rpbm5lciU+JQ0KZ3JvdXBfYnkoY2l0eSkgJT4lDQpzdW1tYXJpc2UobiA9IG4oKSkNCg0KcmVzdF9jaXR5X2Rpbm5lcl9jb3VudCRwZXJjZW50IDwtIA0KICByb3VuZCgocmVzdF9jaXR5X2Rpbm5lcl9jb3VudCRnb29kX2Zvcl9kaW5uZXIgLyByZXN0X2NpdHlfY291bnQkbikqMTAwLCAxKQ0KcmVzdF9jaXR5X2Rpbm5lcl9jb3VudA0KDQoNCmBgYA0KDQpXaGVuIGl0IGNvbWVzIHRvIHJlc3RhdXJhbnRzIHRoYXQgYXJlIGdvb2QgZm9yIGRpbm5lciBhcyBhIHBlcmNlbnRhZ2Ugb2YgdG90YWwgbnVtYmVyIG9mIHJlc3RhdXJhbnRzLCBUb3JvbnRvIGFuZCBQaG9lbml4IHNlZW0gdG8gYmUgYXBwcm94aW1hdGVseSB0aGUgc2FtZSBpbiB0ZXJtcyBvZiBpdHMgcGVyY2VudGFnZSwgZXZlbiB0aG91Z2ggdGhlIGdlb2dyYXBoaWNhbCBjb25jZW50cmF0aW9uIG9mIHBsYWNlcyB0aGF0IGFyZSBnb29kIGZvciBkaW5uZXIgdmFyeSBxdWl0ZSBhIGJpdC4NCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCg0KeWVscF9jaXRpZXMzKHllbHBfZmxhdDEsICJNb250culhbCIsIC03My43NiwgLTczLjUyLCA0NS40MiwgNDUuNiwgDQogICAgICAgICAgICAgIkxvY2F0aW9uIG9mIHJlc3RhdXJhbnRzIGluIE1vbnRyZWFsIikNCg0KYGBgDQoNCkxvb2tpbmcgYmFjayB0byBNb250cmVhbCBhZ2FpbiBvbmUgbGFzdCB0aW1lLCB3ZSBzZWUgdGhhdCBkaW5uZXIgcGxhY2VzIGFyZSBub3QgYXMgcHJldmFsZW50IGFzIGluIFRvcm9udG8gb3IgUGhvZW5peC4gT25seSBwYXJ0cyBvZiB0aGUgZG93bnRvd24gY29yZSBhbmQgaW4gV2VzdG1vdW50IHRvIHRoZSBpbW1lZGlhdGUgc291dGh3ZXN0IG9mIHRoZSBkb3dudG93biBjb3JlIGhhdmUgaGlnaCBjb25jZW50cmF0aW9ucyBvZiBwbGFjZXMgdGhhdCBhcmUgZ29vZCBmb3IgZGlubmVyLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoID0gNy41fQ0KDQoNCiNDb2RlIGJlbG93IGNyZWF0ZXMgYSBzY2F0dGVycGxvdCBvZiByYXRpbmdzIHZzIHJldmlld3MgYWNyb3NzIA0KI2FsbCBZZWxwLXJhdGVkIGVzdGFibGlzaG1lbnRzLCBjb2xvdXIgYnkgb3BlbiB2cyBub3Qgb3BlbiANCg0KI0FzIHBlciBlYXJsaWVyIHJldmlld2VyIHN1Z2dlc3Rpb24sIEkgcHV0IGluIGdlb21faml0dGVyIGFuZCBzZXQgYWxwaGENCiNoaWdoIGVub3VnaCB0byBiZSBhYmxlIHRvIHNlZSB0aGUgcmVkIGRvdHMgY2xlYXJseQ0Kc3RhcnNfcmV2aWV3c19wbG90IDwtIGZ1bmN0aW9uKGRhdGFzZXQsIHRpdGxlbmFtZSkgew0KZ2dwbG90KGFlcyh4ID0gcmV2aWV3X2NvdW50LCB5ID0gc3RhcnMpLCBkYXRhID0gZGF0YXNldCkgKyANCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gZmFjdG9yKGlzX29wZW4pKSkgKw0KICBzY2FsZV9jb2xvcl9kaXNjcmV0ZShuYW1lPSJPcGVyYXRpbmcgc3RhdHVzIiwgYnJlYWtzID0gYygwLCAxKSwgDQogIGxhYmVscz1jKCJDbG9zZWQiLCAiT3BlbiIpKSArIA0KICBsYWJzKHRpdGxlID0gdGl0bGVuYW1lKSArIGxhYnMoeCA9ICJOdW1iZXIgb2YgcmV2aWV3cyIpICsgDQogIGxhYnMoeT0gIlJhdGluZyAoaW4gc3RhcnMpIGZyb20gMSB0byA1IikgICsgDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArIA0KICBzY2FsZV94X2NvbnRpbnVvdXMobGltID0gYygwLCA4MDAwKSkgKw0KICBnZW9tX2ppdHRlcihhZXMoY29sb3VyID0gZmFjdG9yKGlzX29wZW4pKSwgYWxwaGEgPSAwLjgpDQp9DQoNCnN0YXJzX3Jldmlld3NfcGxvdCh5ZWxwX2ZsYXQsIA0KIlJlbGF0aW9uc2hpcCBiZXR3ZW4gWWVscCBzdGFycyBhbmQgcmV2aWV3IGNvdW50IikNCg0KYGBgDQoNCldlIG5vdyBzdGVwIGF3YXkgZnJvbSBnZW9ncmFwaGljIGFuYWx5c2lzIGVudGlyZWx5IGFuZCBnbyBiYWNrIHRvIGxvb2tpbmcgYXQgb3ZlcmFsbCByZWxhdGlvbnNoaXBzIGJldHdlZW4gb3VyIG1haW4gdmFyaWFibGVzIG9mIGludGVyZXN0LCBwcmljZSByYW5nZSwgcmV2aWV3IGNvdW50IGFuZCBzdGFycyBvbiBhIG11bHRpdmFyaWF0ZSBsZXZlbC4NCg0KSW4gZWFybGllciBhbmFseXNlcywgdGhlIG1haW4gZm9jdXMgd2FzIGFsd2F5cyBvbiBvcGVyYXRpbmcgcmVzdGF1cmFudHMgd2l0aGluIE5vcnRoIEFtZXJpY2EsIGFuZCBpbiB0aGUgYmVnaW5uaW5nIG9mIHRoZSBhbmFseXNpcywgdGhlcmUgd2FzIG5vdCBtdWNoIGRpc2N1c3Npb24gb24gdGhlIG9wZXJhdGluZyBzdGF0dXMgdmFyaWFibGUsIGlzX29wZW4sIGFuZCByZXZpZXcgY291bnQgd2FzIG1haW5seSBsb29rZWQgYXQgb24gYSBtb3JlIGdlbmVyYWwgYW5kIGdlb2dyYXBoaWMgbGV2ZWwuDQoNCkluIHRoaXMgc2NhdHRlcnBsb3QgYWJvdmUsIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgbnVtYmVyIG9mIHJldmlld3MgYW5kIHN0YXJzIGdpdmVuIGZvciBhIHJlc3RhdXJhbnQgaXMgcXVpdGUgY2xlYXIuIEFsbW9zdCBhbGwgZXN0YWJsaXNobWVudHMgdGhhdCBoYXZlIGFib3ZlIDEwMDAgcmV2aWV3cyBjb250aW51ZSB0byBiZSBvcGVuLCB3aGlsZSBhbG1vc3QgYWxsIG9mIHRoZSBlc3RhYmxpc2htZW50cyB0aGF0IHdlcmUgY2xvc2VkIGhhZCBsZXNzIHRoYW4gMTAwMCByZXZpZXdzLiBXZSBhbHNvIHNlZSBhYm92ZSB0aGF0IHJlc3RhdXJhbnRzIHdpdGggaGlnaGVyIHJldmlldyBjb3VudHMgdGVuZCB0byBiZSBoaWdoZXIgb24gdGhlIHJhdGluZyBzY2FsZSBhcyB2aXJ0dWFsbHkgYWxsIGVzdGFibGlzaG1lbnRzIHRoYXQgaGFkIG1vcmUgdGhhbiAxMDAwIHJldmlld3Mgd2VyZSBnaXZlbiBhIHJhdGluZyBvZiBhdCBsZWFzdCAyLjUgc3RhcnMuDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGggPSA3LjV9DQpyZXN0X2NpdHlfYWxsIDwtIHN1YnNldCh5ZWxwX2ZsYXQxLCAhaXMubmEoYXR0cmlidXRlcy5SZXN0YXVyYW50c1ByaWNlUmFuZ2UyKSAmICAgICAgICAgICAgICAgICANCiAgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNEZWxpdmVyeSkgJiANCiAgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNUYWJsZVNlcnZpY2UpICYNCiAgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNUYWtlT3V0KSkNCg0Kc3RhcnNfcmV2aWV3c19wbG90KHJlc3RfY2l0eV9hbGwsIA0KIlJlbGF0aW9uc2hpcCBiZXR3ZW4gWWVscCBzdGFycyBhbmQgcmV2aWV3IGNvdW50DQphY3Jvc3MgTm9ydGggQW1lcmljYW4gcmVzdGF1cmFudHMiKQ0KDQoNCmBgYA0KDQpUaGUgcmVsYXRpb25zaGlwIHdlIHNhdyBlYXJsaWVyIGJldHdlZW4gbnVtYmVyIG9mIHJldmlld3MgYW5kIHJhdGluZ3MgYWNyb3NzIGNsb3NlZCBhbmQgb3BlbiBlc3RhYmxpc2htZW50cyBob2xkcyB0cnVlIHRvbyBmb3Igb3BlcmF0aW5nIHJlc3RhdXJhbnRzIGluIE5vcnRoIEFtZXJpY2EuDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGggPSA3LjV9DQoNCnBfc3RhcnJldmlldyA8LSByZXN0X2NpdHlfYWxsICU+JQ0KZ3JvdXBfYnkoYXR0cmlidXRlcy5SZXN0YXVyYW50c1ByaWNlUmFuZ2UyLCBzdGFycykgJT4lDQpzdW1tYXJpc2UodG90YWxfYnlfc3RhciA9IHN1bShyZXZpZXdfY291bnQpKSAlPiUNCm11dGF0ZSh0b3RhbCA9IHN1bSh0b3RhbF9ieV9zdGFyKSkgJT4lDQptdXRhdGUocGVyY2VudCA9IHJvdW5kKCh0b3RhbF9ieV9zdGFyLyB0b3RhbCkqMTAwLCAxKSkgJT4lDQptdXRhdGUocGVyY2VudFdlaWdodCA9IGlmZWxzZShwZXJjZW50ID49IDIwLCBwZXJjZW50ICogMi41LCANCiAgICAgICAgICAgICAgIyBjdXN0b20gY29sdW1uIHRvIHdlaWdodCB0aGUgcGVyY2VudCBmb3Igc2l6ZSBvbiB0aGUgcGxvdA0KICAgICAgICAgICAgICAgICAgICBpZmVsc2UocGVyY2VudCA8IDIwICYgcGVyY2VudCA+PSAxNSwgcGVyY2VudCAqIDEuMiwgDQogICAgICAgICAgICAgICAgICAgIGlmZWxzZShwZXJjZW50IDwgMTUgJiBwZXJjZW50ID49IDEwLCBwZXJjZW50LA0KICAgICAgICAgICAgICAgICAgICBpZmVsc2UocGVyY2VudCA8IDEwICYgcGVyY2VudCA+PSA1LCBwZXJjZW50ICogMC44LCAxKSkpKSkNCg0KZ2dwbG90KHBfc3RhcnJldmlldywgYWVzKHggPSBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIsIHkgPSBzdGFycywgDQogIGxhYmVsPXBlcmNlbnQpKSArIA0KICBnZW9tX3BvaW50KGFlcyhzaXplID0gcGVyY2VudFdlaWdodCksIGNvbG91ciA9ICIjOUVDQUUxIiwgYWxwaGEgPSAwLjcpICsNCiAgbGFicyh0aXRsZSA9ICJQZXJjZW50YWdlIG9mIHJldmlldyBjb3VudCBhY3Jvc3MgWWVscCBzdGFycyBhbmQgcHJpY2UgcmFuZ2UgDQogICAgICAgYWNyb3NzIE5vcnRoIEFtZXJpY2FuIHJlc3RhdXJhbnRzIikgKyBsYWJzKHggPSAiUHJpY2UgUmFuZ2UiKSArIA0KICBsYWJzKHk9ICJSYXRpbmcgKGluIHN0YXJzKSBmcm9tIDEgdG8gNSIpICArIA0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKyANCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxLCA1LCAwLjUpKSArIA0KICBnZW9tX3RleHQoaGp1c3QgPSAwLjQsIHZqdXN0ID0gMC4yLCBzaXplID0gNCkgKyANCiAgc2NhbGVfc2l6ZShyYW5nZSA9IGMoMSwyNSksIGd1aWRlID0gIm5vbmUiKSANCg0KYGBgDQoNCldoZW4gd2UgaW5jbHVkZSBwcmljZSByYW5nZSBpbnRvIG91ciBlYXJsaWVyIHNjYXR0ZXJwbG90IGFuZCBoYXZlIHRoZSBwZXJjZW50YWdlIG9mIHJldmlld3MgYXMgdGhlIHNpemUgb2YgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHByaWNlIHJhbmdlIGFuZCByYXRpbmdzLCB3ZSBmaW5kIHZpcnR1YWxseSBhbGwgcmV2aWV3cyBhcmUgZm9yIHJlc3RhdXJhbnRzIHRoYXQgaGF2ZSBiZXR3ZWVuIGEgMy41LTQuNSByYXRpbmcgb24gWWVscCwgYW5kIHRoYXQgdGhpcyBpcyBjb25zaXN0ZW50IGFjcm9zcyBhbGwgcHJpY2UgcmFuZ2VzLiBIb3dldmVyLCB0aGUgcGVyY2VudCBvZiB0b3RhbCByZXZpZXcgY291bnRzIHdpdGhpbiBlYWNoIHByaWNlIHJhbmdlIGFuZCBzdGFycyBjb21iaW5hdGlvbiBhdCBhIFllbHAgc3RhciBvZiAzIG9yIGxvd2VyIGRlY2xpbmVzIGFzIHRoZSBwcmljZSByYW5nZSBnZXRzIGhpZ2hlci4gVGhpcyBpcyBvZiBjb3Vyc2UgY29uc2lzdGVudCB3aXRoIHRoZSBsaW5lIHBsb3Qgc2hvd24gcHJldmlvdXNseSB3aGVyZSB0aGUgYXZlcmFnZSBzdGFycyBnaXZlbiB0ZW5kZWQgdG8gZ28gdXAgYXMgdGhlIHByaWNlIHJhbmdlIGluY3JlYXNlZC4NCg0KTm93LCBpdCBpcyB0aW1lIHRvIGRvIHNvbWUgZGVlcGVyIGFuYWx5c2lzIGludG8gdGhlIGRpc3RyaWJ1dGlvbiBvZiBZZWxwIHN0YXJzIGFjcm9zcyBkaWZmZXJlbnQgZ2VvZ3JhcGhpZXMgYW5kIHR5cGVzIG9mIGVzdGFibGlzaG1lbnRzLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoID0gNy41fQ0KDQojRnVuY3Rpb24gYmVsb3cgaXMgdG8gY3JlYXRlIGEgZ3JpZCBvZiB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBwZXJjZW50YWdlIG9mIGVzdGFibGlzaG1lbnRzIGFjcm9zcyBzdGFyIGxldmVscyB3aXRoaW4gZWFjaCBOb3J0aCBBbWVyaWNhbiBzdGF0ZQ0Kc3RhcnNfZ3JpZCA8LSBmdW5jdGlvbihkYXRhc2V0LCB0aXRsZTEpIHsNCnllbHBfc3RhdGVzdGFyMSA8LSBkYXRhc2V0ICAlPiUNCmdyb3VwX2J5KHN0YXRlLCBzdGFycykgJT4lDQpzdW1tYXJpc2UodG90YWxfYnlfc3RhciA9IG4oKSkgJT4lDQphcnJhbmdlKGRlc2Moc3RhcnMpKSAlPiUNCm11dGF0ZSh0b3RhbCA9IHN1bSh0b3RhbF9ieV9zdGFyKSkgJT4lIA0KbXV0YXRlKHBlcmNlbnQgPSByb3VuZCgodG90YWxfYnlfc3Rhci8gdG90YWwpKjEwMCwgMSkpICU+JQ0KICAjIGN1c3RvbSBjb2x1bW4gdG8gd2VpZ2h0IHRoZSBwZXJjZW50IGZvciBzaXplIG9uIHRoZSBwbG90DQptdXRhdGUocGVyY2VudFdlaWdodCA9IGlmZWxzZShwZXJjZW50ID49IDIwLCBwZXJjZW50ICogMi41LCANCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHBlcmNlbnQgPCAyMCAmIHBlcmNlbnQgPj0gMTUsIHBlcmNlbnQgKiAxLjIsIA0KICAgICAgICAgICAgICAgICAgICBpZmVsc2UocGVyY2VudCA8IDE1ICYgcGVyY2VudCA+PSAxMCwgcGVyY2VudCwNCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHBlcmNlbnQgPCAxMCAmIHBlcmNlbnQgPj0gNSwgcGVyY2VudCAqIDAuOCwgMSkpKSkpDQoNCiNXaXRoaW4gdGhlIHBsb3QsIHdlaWdodCB0aGUgcGVyY2VudGFnZSBvZiByYXRpbmdzIGFzIHRoZSBzaXplIGZvciBhIHBhcnRpY3VsYXIgcmF0aW5nIGF0IGluY3JlbWVudHMgb2YgMC41LCBzZXQgYW4gYWxwaGEgdmFsdWUgb2YgMC41IHRvIGNyZWF0ZSBzb21lIHRyYW5zcGFyZW5jeSwgYW5kIGFkanVzdCB0aGUgbGFiZWwgdGV4dCBmb3IgcGVyY2VudCB0byBiZSBjZW50ZXJlZCBvbiBlYWNoIGNpcmNsZQ0KDQpnZ3Bsb3QoeWVscF9zdGF0ZXN0YXIxLCBhZXMoeCA9IHN0YXRlLCB5ID0gc3RhcnMsIGxhYmVsID0gcGVyY2VudCkpICsgDQogIGdlb21fcG9pbnQoYWVzKHNpemUgPSBwZXJjZW50V2VpZ2h0ICogMS43NSwgY29sb3VyID0gc3RhcnMpLCBhbHBoYSA9IDAuNSkgKyANCiAgZ2VvbV90ZXh0KGhqdXN0ID0gMC40LCB2anVzdCA9IDAuMiwgc2l6ZSA9IDQpICsgDQogIHNjYWxlX3NpemUocmFuZ2UgPSBjKDEsMjUpLCBndWlkZSA9ICJub25lIikgKyANCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93ID0gInllbGxvdyIsIGhpZ2ggPSAicmVkIikgKyANCiAgbGFicyh0aXRsZSA9IHRpdGxlMSwgeCA9ICJzdGF0ZSIsIA0KICAgICAgIHkgPSAiUGVyY2VudGFnZSB3ZWlnaHQgb2YgcmF0aW5ncyBhY3Jvc3MgYSAxLTUgc2NhbGUiKSArIA0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEsIDUsIDAuNSkpICsgDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSANCn0NCg0Kc3RhcnNfZ3JpZCh5ZWxwX2ZsYXQxLCAiQSBncmlkIG9mIHRoZSBkaXN0cmlidXRpb24gb2YgWWVscCBzdGFycyBieSBzdGF0ZSIpDQpgYGANCg0KSXQgc2VlbXMgbGlrZSBhY3Jvc3MgYWxsIFllbHAgZXN0YWJsaXNobWVudHMgKGJvdGggb3BlbiBhbmQgY2xvc2VkLCB3aGV0aGVyIGEgcmVzdGF1cmFudCBvciBub3QpLCBBcml6b25hIGFuZCBOZXZhZGEgc2VlbSB0byBoYXZlIGEgbXVjaCBsYXJnZXIgcGVyY2VudGFnZSBvZiB0aGVpciBlc3RhYmxpc2htZW50cyBiZWluZyByYXRlZCBhdCA0IHN0YXJzIG9yIGhpZ2hlciwgYW5kIHRoaXMgaXMgbW9yZSBwcm9ub3VuY2VkIGF0IDUgc3RhcnMuIA0KDQpPdXIgbWFpbiBlc3RhYmxpc2htZW50cyBvZiBpbnRlcmVzdCwgaG93ZXZlciwgYXJlIGZvciBvcGVyYXRpbmcgcmVzdGF1cmFudHMsIGFuZCBub3QgbmVjZXNzYXJpbHkganVzdCBhbnkgdHlwZSBvZiBlc3RhYmxpc2htZW50LCBhcyBZZWxwLXJhdGVkIGVzdGFibGlzaG1lbnRzIGNvdWxkIGluY2x1ZGUgbmFpbCBzYWxvbnMsIHNwYXMsIGNvbW11bml0eSBjZW50cmVzIGFzIGRlc2NyaWJlZCBlYXJsaWVyIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhpcyBwcm9qZWN0Lg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoID0gNy41fQ0Kc3RhcnNfZ3JpZChyZXN0XzAsICJBIGdyaWQgb2YgdGhlIGRpc3RyaWJ1dGlvbiBvZiBZZWxwIHN0YXJzIGJ5IHN0YXRlDQogICAgICAgICAgIGZvciBOb3J0aCBBbWVyaWNhbiByZXN0YXVyYW50cyAiKQ0KYGBgDQoNCldoZW4gd2Ugb25seSBsb29rIGF0IG9wZXJhdGluZyByZXN0YXVyYW50cywgd2UgZmluZCB0aGF0IHRoZSBzdG9yeSBjaGFuZ2VzIHF1aXRlIGEgYml0LiBJbnN0ZWFkIG9mIGhhdmluZyBBcml6b25hIGFuZCBOZXZhZGEgZG9taW5hdGUgdGhlIHJhbmtpbmdzIGluIHRoZSA0LjUgdG8gNSBzdGFycyByYW5nZSwgd2Ugc2VlIHRoYXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiBzdGFycyBhY3Jvc3MgYWxsIHN0YXRlcyBpcyByZWxhdGl2ZWx5IHRoZSBzYW1lIGFuZCBjZW50cmVkIGFyb3VuZCAzLjUgdG8gNCBzdGFycy4gSXQgaXMgaW50ZXJlc3RpbmcgdG8gbm90ZSB0aGF0IFF1ZWJlYyBzZWVtcyB0byBoYXZlIGEgZmFyIGhpZ2hlciBwZXJjZW50YWdlIG9mIHJlc3RhdXJhbnRzIGluIGhpZ2hlciBzdGFyIHJhbmdlcyB0aGFuIG90aGVyIHN0YXRlcyBzdWNoIGFzIEFyaXpvbmEgb3IgU291dGggQ2Fyb2xpbmEuIA0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KI0NhbGwgdGhlIGF2ZzEgZnVuY3Rpb24gdG8gY2FsY3VsYXRlIHRoZSBhdmVyYWdlIHN0YXJzIGJ5IHN0YXRlDQphdmcxKHJlc3RfMCwgc3RhdGUsIHN0YXJzKQ0KYGBgDQoNClRoaXMgY2FuIGJlIHNlZW4gaW4gdGhlIGF2ZXJhZ2Ugc3RhcnMgYnkgc3RhdGUgY2hhcnQgYmVsb3cuDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGggPSA3LjV9DQoNCiNUaGUgZnVuY3Rpb24gYmVsb3cgaXMgdG8gY3JlYXRlIGEgc3Vic2V0IG9mIHRoZSBkYXRhIHNldCBmb3IgZWFjaCBub2lzZSBsZXZlbCBhcyByZXByZXNlbnRlZCBieSB2YXIxLCB0aGVuIGl0IHRha2VzIHRoaXMgbmV3IHN1YnNldCBhbmQgZ3JvdXBzIGJ5IHRoZSBwcmljZSByYW5nZSBhbmQgY2FsY3VsYXRlcyB0aGUgYXZlcmFnZSBudW1iZXIgb2YgWWVscCBzdGFycyBmb3IgZWFjaCBwcmljZSByYW5nZSBvZiAxLCAyLCAzLCBhbmQgNC4NCg0KcmVzdF8wX25vaXNlIDwtIGZ1bmN0aW9uKGRhdGFzZXQsIHZhcjEpIHsNCiANCnJlc3RfMF9ub2lzZSA8LSAgc3Vic2V0KGRhdGFzZXQsICFpcy5uYShhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIpICYgDQogIGlzX29wZW4gPT0gMSAmICFpcy5uYShhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzVGFrZU91dCkgJiANCiAgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNEZWxpdmVyeSkgJiANCiAgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNUYWJsZVNlcnZpY2UpICYgYXR0cmlidXRlcy5Ob2lzZUxldmVsID09IHZhcjEpDQogIA0KcmVzdF9wX25vaXNlIDwtIHJlc3RfMF9ub2lzZSAlPiUNCmdyb3VwX2J5KGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNQcmljZVJhbmdlMikgJT4lDQpzdW1tYXJpc2Uobj1tZWFuKHN0YXJzKSkNCn0NCg0KIzQgc2VwYXJhdGUgZGF0YXNldHMgYXJlIGNyZWF0ZWQgZm9yIGVhY2ggaW5zdGFuY2Ugb2Ygbm9pc2UgbGV2ZWwgYnkgY2FsbGluZyB0aGUgZnVuY3Rpb24gY3JlYXRlZCBlYXJsaWVyDQpyZXN0X3BfcXVpZXQgPC0gcmVzdF8wX25vaXNlKHllbHBfZmxhdDEsICJxdWlldCIpDQpyZXN0X3BfYXZnIDwtIHJlc3RfMF9ub2lzZSh5ZWxwX2ZsYXQxLCAiYXZlcmFnZSIpDQpyZXN0X3BfbG91ZCA8LSByZXN0XzBfbm9pc2UoeWVscF9mbGF0MSwgImxvdWQiKQ0KcmVzdF9wX3Zlcnlsb3VkIDwtIHJlc3RfMF9ub2lzZSh5ZWxwX2ZsYXQxLCAidmVyeV9sb3VkIikNCg0KI1RoaXMgcGxvdHMgZWFjaCBvZiB0aGUgNCBsaW5lcyBvbnRvIG9uZSBwbG90IHRvIHNob3cgaG93IHN0YXJzIGFuZCBwcmljZSByYW5nZSBkaWZmZXIgYWNyb3NzIGRpZmZlcmVudCBub2lzZSBsZXZlbHMNCmdncGxvdCgpICsgDQogIGdlb21fbGluZShkYXRhID0gcmVzdF9wX3F1aWV0LCBhZXMoeCA9IGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNQcmljZVJhbmdlMiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gbiwgY29sb3VyID0gInF1aWV0IiksIHNpemUgPSAwLjUpICsNCiAgZ2VvbV9saW5lKGRhdGEgPSByZXN0X3BfYXZnLCBhZXMoeCA9IGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNQcmljZVJhbmdlMiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IG4sIGNvbG91ciAgPSAiYXZlcmFnZSIpLCBzaXplID0gMC41KSArDQogIGdlb21fbGluZShkYXRhID0gcmVzdF9wX2xvdWQsIGFlcyh4ID0gYXR0cmlidXRlcy5SZXN0YXVyYW50c1ByaWNlUmFuZ2UyLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IG4sIGNvbG91ciAgPSAibG91ZCIpLCBzaXplID0gMC41KSArIA0KICBnZW9tX2xpbmUoZGF0YSA9IHJlc3RfcF92ZXJ5bG91ZCwgYWVzKHggPSBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gbiwgY29sb3VyICA9ICJ2ZXJ5IGxvdWQiKSwgc2l6ZSA9IDAuNSkgKw0KICB4bGFiKCJQcmljZSByYW5nZSIpICsNCiAgeWxhYigiU3RhcnMiKSArIA0KICBzY2FsZV9jb2xvdXJfbWFudWFsKG5hbWUgPSAiTm9pc2UgbGV2ZWwiLCANCiAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXM9YygicmVkIiwgImJsdWUiLCAiZ3JlZW4iLCAiYnJvd24iKSkgKyANCiAgbGFicyh0aXRsZSA9ICJSZWxhdGlvbnNoaXAgYmV0d2VlbiBzdGFycyBhbmQgcHJpY2UgcmFuZ2UgDQogICAgICAgYWNyb3NzIGRpZmZlcmVudCBub2lzZSBsZXZlbHMiKSArIA0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkNCg0KYGBgDQoNCkFzaWRlIGZyb20gZ2VvZ3JhcGh5LCB0aGVyZSBhcmUgYWxzbyBvdGhlciB2YXJpYWJsZXMgc3VjaCBhcyBub2lzZSBsZXZlbHMgYW5kIGFsY29ob2wgc2VydmljZSB0aGF0IEkgd291bGQgbGlrZSB0byBleHBsb3JlIGluIHRlcm1zIG9mIGl0cyByZWxhdGlvbiB0byBvdXIgbWFpbiB2YXJpYWJsZXMgb2YgaW50ZXJlc3QsIHByaWNlIHJhbmdlIGFuZCBzdGFycy4NCg0KRWFybGllciwgd2Ugc2F3IHRoYXQgd2hlbmV2ZXIgbm9pc2UgbGV2ZWxzIHdlcmUgaGlnaGVyLCB0aGUgYXZlcmFnZSBudW1iZXIgb2YgWWVscCBzdGFycyBmb3IgYSByZXN0YXVyYW50IHdhcyBsb3dlciwgcmVzdWx0aW5nIGluIGEgY2xlYXIgZG93bndhcmQgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIHR3byB2YXJpYWJsZXMuIEhvd2V2ZXIsIHdoZW4gd2UgY3JlYXRlIGEgbXVsdGl2YXJpYXRlIHBsb3QgdG8gZ3JvdXAgdGhpcyByZWxhdGlvbnNoaXAgYnkgcHJpY2UgcmFuZ2UsIHdlIGZpbmQgdGhhdCBhY3Jvc3MgZWFjaCBwcmljZSByYW5nZSwgYSByZXN0YXVyYW50IHRoYXQgaXMgbG91ZGVyIHdpbGwgYWx3YXlzIGhhdmUgYSBsb3dlciBhdmVyYWdlIHJhdGluZyAodGhvdWdoIHRoZSBlZmZlY3QgaXMgbWlub3IgYmV0d2VlbiBhdmVyYWdlIHZlcnN1cyBxdWlldCBub2lzZSBsZXZlbHMpLiBUaGUgb25seSBub3RhYmxlIGV4Y2VwdGlvbiBpcyBhdCBwcmljZSByYW5nZSAzLCB3aGVyZSBhIHJlc3RhdXJhbnQgd2l0aCBhbiBhdmVyYWdlIG5vaXNlIGxldmVsIGRvZXMgc2xpZ2h0bHkgYmV0dGVyIHRoYW4gdGhvc2UgYXQgYSBxdWlldCBub2lzZSBsZXZlbC4NCg0KQWxzbywgaXQgaXMgaW50ZXJlc3RpbmcgdGhhdCBhdCB0aGUgbW9zdCBleHBlbnNpdmUgcHJpY2UgcmFuZ2UgNCwgdGhlIGF2ZXJhZ2Ugc3RhcnMgZm9yIGEgdmVyeSBsb3VkIHJlc3RhdXJhbnQgZGVjcmVhc2VzIGNvbXBhcmVkIHRvIHRob3NlIGF0IHRoZSBwcmljZSByYW5nZSAzLCB3aGlsZSBmb3IgYSBxdWlldCByZXN0YXVyYW50LCB0aGUgaW5jcmVhc2UgaW4gdGhlIGF2ZXJhZ2UgbnVtYmVyIG9mIHN0YXJzIGZyb20gcHJpY2UgcmFuZ2UgMyBpcyBtdWNoIGdyZWF0ZXIgdGhhbiBpbiBwcmV2aW91cyBwcmljZSByYW5nZXMuIEFzIGEgcmVzdWx0LCB0aGUgZGlmZmVyZW5jZSBpbiBhdmVyYWdlIHN0YXJzIGdpdmVuIGZvciBhIHZlcnkgbG91ZCB2ZXJzdXMgYSBxdWlldCByZXN0YXVyYW50IGF0IHRoZSBtb3N0IGV4cGVuc2l2ZSBwcmljZSByYW5nZSA0IGlzIGEgZGlmZmVyZW5jZSBvZiBhbG1vc3QgMSB3aG9sZSBzdGFyIQ0KDQpOZXh0LCBsZXQgdXMgcGVyZm9ybSBhIHNpbWlsYXIgYW5hbHlzaXMgYWNyb3NzIGFsY29ob2wgc2VydmljZSBsZXZlbHMuDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGggPSA3LjV9DQoNCiNUaGUgZnVuY3Rpb24gYmVsb3cgaXMgdG8gY3JlYXRlIGEgc3Vic2V0IG9mIHRoZSBkYXRhIHNldCBmb3IgZWFjaCBhbGNvaG9sIHNlcnZpY2UgYXMgcmVwcmVzZW50ZWQgYnkgdmFyMSwgdGhlbiBpdCB0YWtlcyB0aGlzIG5ldyBzdWJzZXQgYW5kIGdyb3VwcyBieSB0aGUgcHJpY2UgcmFuZ2UgYW5kIGNhbGN1bGF0ZXMgdGhlIGF2ZXJhZ2UgbnVtYmVyIG9mIFllbHAgc3RhcnMgZm9yIGVhY2ggcHJpY2UgcmFuZ2Ugb2YgMSwgMiwgMywgYW5kIDQuDQoNCnJlc3RfMF9hbGNvaG9sPC0gZnVuY3Rpb24oZGF0YXNldCwgdmFyMSkgew0KIA0KcmVzdF8wX2FsY29ob2wgPC0gIHN1YnNldChkYXRhc2V0LCBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIgIT0gIk5BIiAmDQogIGlzX29wZW4gPT0gMSAmICFpcy5uYShhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzVGFrZU91dCkgJiANCiAgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNEZWxpdmVyeSkgJiANCiAgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNUYWJsZVNlcnZpY2UpICYgYXR0cmlidXRlcy5BbGNvaG9sID09IHZhcjEpDQogIA0KcmVzdF9wX2FsY29ob2wgPC0gcmVzdF8wX2FsY29ob2wgJT4lDQpncm91cF9ieShhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIpICU+JQ0Kc3VtbWFyaXNlKG49bWVhbihzdGFycykpDQp9DQoNCiM0IHNlcGFyYXRlIGRhdGFzZXRzIGFyZSBjcmVhdGVkIGZvciBlYWNoIGluc3RhbmNlIG9mIG5vaXNlIGxldmVsIGJ5IGNhbGxpbmcgdGhlIGZ1bmN0aW9uIGNyZWF0ZWQgZWFybGllcg0KcmVzdF9wX25vbmUgPC0gcmVzdF8wX2FsY29ob2woeWVscF9mbGF0MSwgIm5vbmUiKQ0KcmVzdF9wX2JlZXJ3aW5lIDwtIHJlc3RfMF9hbGNvaG9sKHllbHBfZmxhdDEsICJiZWVyX2FuZF93aW5lIikNCnJlc3RfcF9mdWxsYmFyIDwtIHJlc3RfMF9hbGNvaG9sKHllbHBfZmxhdDEsICJmdWxsX2JhciIpDQoNCiNUaGlzIHBsb3RzIGVhY2ggb2YgdGhlIDQgbGluZXMgb250byBvbmUgcGxvdCB0byBzaG93IGhvdyBzdGFycyBhbmQgcHJpY2UgcmFuZ2UgZGlmZmVyIGFjcm9zcyBkaWZmZXJlbnQgbm9pc2UgbGV2ZWxzDQpnZ3Bsb3QoKSArIA0KICBnZW9tX2xpbmUoZGF0YSA9IHJlc3RfcF9ub25lLCBhZXMoeCA9IGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNQcmljZVJhbmdlMiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gbiwgY29sb3VyID0gIm5vbmUiKSwgc2l6ZSA9IDAuNSkgKw0KICBnZW9tX2xpbmUoZGF0YSA9IHJlc3RfcF9iZWVyd2luZSwgYWVzKHggPSBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBuLCBjb2xvdXIgID0gImJlZXIgKyB3aW5lIiksIHNpemUgPSAwLjUpICsNCiAgZ2VvbV9saW5lKGRhdGEgPSByZXN0X3BfZnVsbGJhciwgYWVzKHggPSBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBuLCBjb2xvdXIgID0gImZ1bGwgYmFyIiksIHNpemUgPSAwLjUpICsgDQogIHhsYWIoIlByaWNlIHJhbmdlIikgKw0KICB5bGFiKCJTdGFycyIpICsgDQogIHNjYWxlX2NvbG91cl9tYW51YWwobmFtZSA9ICJBbGNvaG9sIHNlcnZpY2UgbGV2ZWwiLCANCiAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXM9YygicHVycGxlIiwgIm9yYW5nZSIsICJ5ZWxsb3ciKSkgKyANCiAgbGFicyh0aXRsZSA9ICJSZWxhdGlvbnNoaXAgYmV0d2VlbiBzdGFycyBhbmQgcHJpY2UgcmFuZ2UNCiAgICAgIGFjcm9zcyBkaWZmZXJlbnQgYWxjb2hvbCBzZXJ2aWNlIGxldmVscyIpICsgDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQ0KDQpgYGANCg0KVGhlIHN0b3J5IGJlaGluZCBhbGNvaG9sIHNlcnZpY2UgbGV2ZWxzIHNlZW0gdG8gYmUgYSBkaWZmZXJlbnQgdGhhbiB3YXMgdGhlIGNhc2UgZm9yIG5vaXNlIGxldmVscy4gUmVzdGF1cmFudHMgd2l0aCBncmVhdGVyIGFsY29ob2wgc2VydmljZSBkbyBub3QgbmVjZXNzYXJpbHkgaGF2ZSBtb3JlIFllbHAgc3RhcnMgb24gYXZlcmFnZSB0aGFuIHRob3NlIHdpdGggbGVzcyBhbGNvaG9sIHNlcnZpY2UuIEFzIG9uZSBjYW4gc2VlIG9uIHRoZSBwbG90IGJlbG93LCByZXN0YXVyYW50cyB0aGF0IG9ubHkgb2ZmZXIgYmVlciBhbmQgd2luZSBpbnN0ZWFkIG9mIGEgZnVsbCBiYXIgYWxtb3N0IGFsd2F5cyBjb25zaXN0ZW50bHkgb3V0cGVyZm9ybSByZXN0YXVyYW50cyB3aXRoIGEgZnVsbCBiYXIgYWxjb2hvbCBzZXJ2aWNlIGFuZCB0aGlzIGRpZmZlcmVuY2UgYmVjb21lcyBtdWNoIGdyZWF0ZXIgYXQgdGhlIGhpZ2hlc3QgcHJpY2UgcmFuZ2UgNC4gSG93ZXZlciwgaW4gdGhlIGNhc2Ugb2YgbW9yZSBleHBlbnNpdmUgMy00IHByaWNlIHJhbmdlIHJlc3RhdXJhbnRzLCByZXN0YXVyYW50cyB0aGF0IG9mZmVyIGF0IGxlYXN0IGJlZXIgYW5kIHdpbmUgb3V0cGVyZm9ybSByZXN0YXVyYW50cyB0aGF0IGRvIG5vdCBwcm92aWRlIGFsY29ob2wgYnkgMSB3aG9sZSBzdGFyIQ0KDQoNCk5vdywgd2UgaGF2ZSBhbmFseXplZCBzbyBtYW55IGRpZmZlcmVudCByZWxhdGlvbnNoaXBzIGJldHdlZW4gcHJpY2UgcmFuZ2UgYW5kIHN0YXJzLiBJIHdvbmRlciB3aGljaCBvZiB0aGUgdmFyaWFibGVzIHdlIGFuYWx5emVkIGVhcmxpZXIgaGF2ZSB0aGUgbW9zdCBpbXBhY3Qgb24gdGhlIFllbHAgc3RhcnMgYW4gb3BlcmF0aW5nIHJlc3RhdXJhbnQgaW4gTm9ydGggQW1lcmljYSBtaWdodCByZWNlaXZlLiBXZSBhcmUgZ29pbmcgdG8gZG8gdGhpcyBieSBjcmVhdGluZyBhIGxpbmVhciBtb2RlbCB0aGF0IHRha2VzIGludG8gYWNjb3VudCBhbGwgdGhlIG90aGVyIHZhcmlhYmxlcyB3ZSBleHBsb3JlZCBhcyBpbmRlcGVuZGVudCB2YXJpYWJsZXMgd2l0aCBzdGFycyBhcyB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQoNCnJlc3RfbG1fc3RhcnMgPC0gc3Vic2V0KHllbHBfZmxhdDEsICFpcy5uYShpc19vcGVuKSAmIA0KICAhaXMubmEoYXR0cmlidXRlcy5SZXN0YXVyYW50c0F0dGlyZSkgJiANCiAgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNHb29kRm9yR3JvdXBzKSAmIA0KICAhaXMubmEoYXR0cmlidXRlcy5Ob2lzZUxldmVsKSAmICFpcy5uYShhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzUHJpY2VSYW5nZTIpICYNCiAgIWlzLm5hKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNUYWtlT3V0KSAmIA0KICAhaXMubmEoYXR0cmlidXRlcy5SZXN0YXVyYW50c0RlbGl2ZXJ5KSAmIA0KICAhaXMubmEoYXR0cmlidXRlcy5SZXN0YXVyYW50c1RhYmxlU2VydmljZSkpDQoNCnN0YXJzX2xtIDwtIGxtKHN0YXJzIH4gYXR0cmlidXRlcy5SZXN0YXVyYW50c1ByaWNlUmFuZ2UyICsgDQogIGF0dHJpYnV0ZXMuTm9pc2VMZXZlbCArIGF0dHJpYnV0ZXMuQWxjb2hvbCArIHJldmlld19jb3VudCArIGlzX29wZW4gKyANCiAgYXR0cmlidXRlcy5SZXN0YXVyYW50c0dvb2RGb3JHcm91cHMgKyBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzQXR0aXJlICsgDQogIGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNEZWxpdmVyeSAgKyBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzVGFrZU91dCArIA0KICBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzVGFibGVTZXJ2aWNlLCBkYXRhID0gc3Vic2V0KHJlc3RfbG1fc3RhcnMpKQ0KDQpzdW1tYXJ5KHN0YXJzX2xtKQ0KDQpgYGANCg0KQXMgd2UgaGFkIHNlZW4gaW4gc29tZSBvZiB0aGUgZWFybGllciByZWdyZXNzaW9ucyBhbmQvb3IgYW5hbHlzZXMsIGluY3JlYXNlZCBwcmljZSByYW5nZXMsIGJlaW5nIG9wZW4sIGhhdmluZyBubyBhbGNvaG9sIHNlcnZpY2Ugb3IgYSBmdWxsIGJhciwgaGF2aW5nIGEgaGlnaGVyIHJldmlldyBjb3VudCBhbmQgaGF2aW5nIGxvd2VyIG5vaXNlIGxldmVscyB3ZXJlIGNvcnJlbGF0ZWQgd2l0aCBhIGhpZ2hlciByYXRpbmcuIE90aGVyIG5ldyByZWxhdGlvbnNoaXBzIGluY2x1ZGUgdGhlIGZhY3QgdGhhdCB3ZSBuZXZlciBsb29rZWQgYXQgaW4gaXRzIHJlbGF0aW9uc2hpcCB0byBZZWxwIHN0YXJzIHdlcmUgcmVzdGF1cmFudCBkaW5pbmcgb3B0aW9ucywgaW4gd2hpY2ggaGF2aW5nIHRhYmxlIHNlcnZpY2UgY29ycmVsYXRlZCBoaWdobHkgd2l0aCBzdGFycywgdGhvdWdoIGhhdmluZyB0YWtlb3V0IGFwcGFyZW50bHkgaXMgbm90Lg0KDQpOb25ldGhlbGVzcywgdGhlIHBlcmNlbnRhZ2Ugb2YgdmFyaWFuY2UgKDYuNSUpIGV4cGxhaW5lZCBieSB0aGlzIG1vZGVsIGlzIG5vdCB2ZXJ5IGhpZ2gsIGFuZCB0aGlzIHN1Z2dlc3RzIHRoYXQgbWFueSBvdGhlciB2YXJpYWJsZXMgc3VjaCBhcyBmb29kIHF1YWxpdHksIHR5cGUgb2YgY3Vpc2luZSwgcmVjb21tZW5kYXRpb24gZnJvbSBhIGZyaWVuZCB3ZXJlIGV0Yy4gY291bGQgaGVscCB0byBpbXByb3ZlIHRoaXMgbW9kZWwuDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCnByaWNlX2xtIDwtIGxtKGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNQcmljZVJhbmdlMiB+IHN0YXJzICsgDQogIGF0dHJpYnV0ZXMuTm9pc2VMZXZlbCArIGF0dHJpYnV0ZXMuQWxjb2hvbCArIHJldmlld19jb3VudCArIGlzX29wZW4gKyANCiAgYXR0cmlidXRlcy5SZXN0YXVyYW50c0dvb2RGb3JHcm91cHMgKyBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzQXR0aXJlICsgDQogIGF0dHJpYnV0ZXMuUmVzdGF1cmFudHNEZWxpdmVyeSAgKyBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzVGFrZU91dCArIA0KICBhdHRyaWJ1dGVzLlJlc3RhdXJhbnRzVGFibGVTZXJ2aWNlLCBkYXRhID0gc3Vic2V0KHJlc3RfbG1fc3RhcnMpKQ0KDQpzdW1tYXJ5KHByaWNlX2xtKQ0KDQpgYGANCg0KT24gdGhlIG90aGVyIGhhbmQsIHdoZW4gYSBsaW5lYXIgbW9kZWwgaXMgYnVpbHQgd2l0aCB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGUgYmVpbmcgc3RhcnMgYW5kIGl0IGlzIHVzZWQgdG8gcHJlZGljdCB0aGUgcHJpY2UgcmFuZ2Ugb2YgYSByZXN0YXVyYW50LCB3ZSBmaW5kIHRoYXQgdGhlIHZhcmlhYmxlcyBjaG9zZW4gZG8gYSBmYWlybHkgZ29vZCBqb2IgYXQgcHJlZGljdGluZyBob3cgZXhwZW5zaXZlIGEgcmVzdGF1cmFudCB3aWxsIGJlLCBhcyBvdmVyIDQ2JSBvZiB0aGUgdmFyaWFuY2UgaW4gdGhlIG1vZGVsIGlzIGV4cGxhaW5lZCBieSB0aGVzZSB2YXJpYWJsZXMgYWxvbmUuIA0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoID0gNy41fQ0KDQp5ZWxwX29wZW4xIDwtIHN1YnNldCh5ZWxwX2ZsYXQsIGlzX29wZW4gPT0gMSkNCnllbHBfc3RhcnMoeWVscF9vcGVuMSwgJ0Rpc3RyaWJ1dGlvbiBvZiBZZWxwIHN0YXJzIGFjcm9zcyBvcGVyYXRpbmcgZXN0YWJsaXNobWVudHMnKQ0KDQoNCmBgYA0KIyBNdWx0aXZhcmlhdGUgQW5hbHlzaXMNCg0KIyMjICBUYWxrIGFib3V0IHNvbWUgb2YgdGhlIHJlbGF0aW9uc2hpcHMgeW91IG9ic2VydmVkIGluIHRoaXMgcGFydCBvZiB0aGUgaW52ZXN0aWdhdGlvbi4gV2VyZSB0aGVyZSBmZWF0dXJlcyB0aGF0IHN0cmVuZ3RoZW5lZCBlYWNoIG90aGVyIGluIHRlcm1zIG9mIGxvb2tpbmcgYXQgeW91ciBmZWF0dXJlKHMpIG9mIGludGVyZXN0Pw0KDQoxKSBJbiBUb3JvbnRvIGFuZCBQaG9lbml4LCByZXN0YXVyYW50cyBvZiB2YXJ5aW5nIG5vaXNlIGxldmVscyBhcmUgYWxsIG92ZXIgdGhlIGNpdHkuDQoNCjIpIEluIHRlcm1zIG9mIGFsY29ob2wgc2VydmljZSwgdGhlIHN1YnVyYmFuIGFyZWFzIG9mIFRvcm9udG8gYW5kIFBob2VuaXggaGFkIGxlc3MgYWxjb2hvbCBzZXJ2aWNlIGluIHRlcm1zIG9mIGZ1bGwgYmFyIG9yIGJlZXIgYW5kIHdpbmUgdGhhbiBpbiB0aGUgZG93bnRvd24gY29yZSB3aGlsZSBmb3IgTW9udHJlYWwsIGZ1bGwgYmFyIGFsY29ob2wgc2VydmljZSB3YXMgdmlydHVhbGx5IGV2ZXJ5d2hlcmUgaW4gdGhlIGNpdHkuDQoNCjMpIFBsYWNlcyB0aGF0IHdlcmUgZ29vZCBmb3IgZGlubmVyIHdlcmUgZm91bmQgYWxsIG92ZXIgUGhvZW5peCwgd2hpbGUgaW4gVG9yb250bywgdGhlIGhpZ2hlc3QgY29uY2VudHJhdGlvbnMgd2VyZSBmb3VuZCBpbiB0aGUgZG93bnRvd24gY29yZSBhbmQgaW4gdGhlIGNlbnRyYWwgdGhvcm91Z2hmYXJlLCBhbmQgaW4gTW9udHJlYWwsIGRpbm5lciBwbGFjZXMgd2VyZSBvbmxseSBmb3VuZCBpbiB0aGUgZG93bnRvd24gY29yZS4NCg0KNCkgSG9sZGluZyBwcmljZSByYW5nZSBjb25zdGFudCwgYmV0d2VlbiA4MC05MCUgb2YgcmVzdGF1cmFudHMgd2VyZSByYXRlZCBiZXR3ZWVuIDMuNSB0byA0LjUgc3RhcnMuDQoNCjUpIFJlc3RhdXJhbnRzIHRoYXQgaGFkIG5vaXNpZXIgYXRtb3NwaGVyZXMgaGFkIGxvd2VyIGF2ZXJhZ2Ugc3RhcnMgdGhhbiBxdWlldGVyIG9uZXMgYW5kIHRoaXMgd2FzIHRydWUgYWNyb3NzIGFsbCBwcmljZSByYW5nZXMuDQoNCg0KIyMjIFdlcmUgdGhlcmUgYW55IGludGVyZXN0aW5nIG9yIHN1cnByaXNpbmcgaW50ZXJhY3Rpb25zIGJldHdlZW4gZmVhdHVyZXM/DQoNCk9uZSB0aGluZyB0aGF0IEkgZm91bmQgaW50ZXJlc3Rpbmcgd2FzIHRoYXQgcmVzdGF1cmFudHMgdGhhdCBvbmx5IHNlcnZlZCBiZWVyIGFuZCB3aW5lIHRlbmRlZCB0byBkbyBiZXR0ZXIgaW4gdGVybXMgb2YgWWVscCBzdGFycyB0aGFuIHRob3NlIHRoYXQgaGFkIGZ1bGwgYmFyIGFsY29ob2wgc2VydmljZS4NCg0KDQojIyMgT1BUSU9OQUw6IERpZCB5b3UgY3JlYXRlIGFueSBtb2RlbHMgd2l0aCB5b3VyIGRhdGFzZXQ/IERpc2N1c3MgdGhlIHN0cmVuZ3RocyBhbmQgbGltaXRhdGlvbnMgb2YgeW91ciBtb2RlbC4NCg0KSSBjcmVhdGVkIHR3byBsaW5lYXIgbW9kZWxzIHRoYXQgZXhhbWluZWQgdGhlIGltcGFjdCBvZiB0aGUgdmFyaWFibGVzIEkgZGlzY3Vzc2VkIGVhcmxpZXIgb24gcHJpY2UgcmFuZ2UgYW5kIHN0YXJzLiBUaGUgUi1zcXVhcmVkIGZvciB0aGUgbGluZWFyIG1vZGVsIHRoYXQgcHJlZGljdGVkIHN0YXJzIHdhcyBvbmx5IGFyb3VuZCA2JSwgbWVhbmluZyB0aGF0IHdlcmUgZmFyIG1vcmUgZmVhdHVyZXMgdGhhdCBjb3VsZCBoYXZlIGJlZW4gYmV0dGVyIGZvciB0aGUgbW9kZWwgZXZlbiBpZiB0aGUgcmVsYXRpb25zaGlwcyBpbiB0aGUgbW9kZWwgd2VyZSBmb3VuZCB0byBiZSBtb3N0bHkgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBhbmQgY29ycmVsYXRlZCB3ZWxsIHdpdGggdHJlbmRzIHdlIHNhdyBlYXJsaWVyIGluIHRoZSBwbG90cyBhbmFseXNpcy4gSG93ZXZlciwgdGhlIGFtb3VudCBvZiB2YXJpYW5jZSBleHBsYWluZWQgYnkgdGhlIGxpbmVhciBtb2RlbCBvbiBwcmljZSByYW5nZSBwZXJmb3JtZWQgc3Vic3RhbnRpYWxseSBiZXR0ZXIgd2l0aCA0NiUgb2YgdmFyaWFuY2UgYmVpbmcgZXhwbGFpbmVkIGJ5IHRoZSBtb2RlbC4NCg0KDQojIEZpbmFsIFBsb3RzIGFuZCBTdW1tYXJ5DQoNCg0KIyMjIERlc2NyaXB0aW9uIE9uZTogDQoNClRoZSBtYWpvcml0eSBvZiBvcGVyYXRpbmcgZXN0YWJsaXNobWVudHMgaW4gdGhlIHBsb3QgYmVsb3cgd2VyZSByYXRlZCBiZXR3ZWVuIDMgdG8gNSBzdGFycywgd2l0aCBhIHBlYWsgYXQgNCBzdGFycyB3aGVyZSBhbG1vc3QgMjAlIG9mIGVzdGFibGlzaG1lbnRzIGFjaGlldmVkIHRoaXMgcmF0aW5nLg0KVmVyeSBmZXcgZXN0YWJsaXNobWVudHMgKGxlc3MgdGhhbiAxMCUpIHRoYXQgcmVtYWluZWQgb3BlcmF0aW5nIHdlcmUgcmF0ZWQgYmV0d2VlbiAxIHRvIDIgc3RhcnMuDQoNCiMjIyBQbG90IE9uZToNCg0KYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDcuNX0NCmdncGxvdChyZXN0X2NpdHlfdmFsdWUsIGFlcyhyZW9yZGVyKGNpdHksIC12YWx1ZSksIHZhbHVlKSwgbGFiZWw9dmFsdWVfdHlwZSkgKyANCiAgZ2VvbV9iYXIoc3RhdD0naWRlbnRpdHknLCBhZXMoZmlsbD12YWx1ZV90eXBlKSwgd2lkdGg9LjUpICArDQogIHNjYWxlX2ZpbGxfbWFudWFsKG5hbWU9InZhbHVlIiwgDQogICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkFib3ZlIEF2ZXJhZ2UiLCAiQmVsb3cgQXZlcmFnZSIpLCANCiAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYygiYWJvdmUiPSIjMDBiYTM4IiwgImJlbG93Ij0iI2Y4NzY2ZCIpKSArIA0KICBsYWJzKHN1YnRpdGxlPSJOb3JtYWxpc2VkIFllbHAgdmFsdWUgKHJhdGluZ3MpIGZvciBOb3J0aCBBbWVyaWNhbiBjaXRpZXMiLCANCiAgICAgICB0aXRsZT0gIkNvbXBhcmlzb24gb2YgcmVzdGF1cmFudCB2YWx1ZSBhY3Jvc3MgbWFqb3IgTm9ydGggQW1lcmljYW4gY2l0aWVzIikgKyBsYWJzKHg9ImNpdHkiKSArDQogIGNvb3JkX2ZsaXAoKQ0KYGBgDQoNCiMjIyBEZXNjcmlwdGlvbiBUd286DQoNCldlIGRlZmluZWQgdmFsdWUgZWFybGllciBhcyBzdGFycyBkaXZpZGVkIGJ5IHByaWNlIHJhbmdlLCB3aGljaCBnaXZlcyB1cyB0aGUgYW1vdW50IG9mIHZhbHVlIHRoYXQgd2UgZGVyaXZlIGZvciBhIGdpdmVuIHByaWNlIHRoYXQgd2UgcGF5IGZvciBvdXIgZm9vZCBhdCBhbiBvcGVyYXRpbmcgcmVzdGF1cmFudC4gSW4gdGhlIGdyYXBoIGFib3ZlLCB3ZSBmaW5kIHRoYXQgd2hlbiBpdCBjb21lcyB0byBnZXR0aW5nIHRoZSBtb3N0ICJiYW5nIGZvciB5b3VyIGJ1Y2siLCB0aGUgY2l0aWVzIG9mIHRoZSBQaG9lbml4IG1ldHJvcG9saXRhbiBhcmVhIChleGNlcHQgZm9yIFNjb3R0c2RhbGUpIGFyZSB0aGUgYmVzdCBmb3IgZXh0cmFjdGluZyBtYXhpbXVtIHZhbHVlIGluIHlvdXIgZGluaW5nIGV4cGVyaWVuY2UgZm9yIHRoZSBhbW91bnQgb2YgbW9uZXkgdGhhdCB5b3UgcGF5Lg0KDQoNCiMjIyBQbG90IFR3bzoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGggPSA3LjV9DQpzdGFyc19ncmlkKHJlc3RfMCwgIkEgZ3JpZCBvZiB0aGUgZGlzdHJpYnV0aW9uIG9mIFllbHAgc3RhcnMgYnkgc3RhdGUNCiAgICAgICAgICAgZm9yIE5vcnRoIEFtZXJpY2FuIHJlc3RhdXJhbnRzICIpDQpgYGANCg0KIyMjIERlc2NyaXB0aW9uIFRocmVlOg0KDQpBY3Jvc3MgYWxsIE5vcnRoIEFtZXJpY2FuIHN0YXRlcywgaXQgc2VlbXMgdGhhdCB2ZXJ5IGZldyByZXN0YXVyYW50cyBhcmUgYWJsZSB0byBnZXQgYSBwZXJmZWN0IDUgc3RhciByYXRpbmcuIFRoYXQgYmVpbmcgc2FpZCwgdGhlIG51bWJlciBvZiByZXN0YXVyYW50cyB0aGF0IHdlcmUgcmF0ZWQgMiBzdGFycyBvciBsZXNzIHdlcmUgYWxzbyBuZWdsaWdpYmxlIGFzIHdlbGwuIEFsbW9zdCBhbGwgcmVzdGF1cmFudHMgYXJlIGNsdXN0ZXJlZCBiZXR3ZWVuIDMgc3RhcnMgdG8gNC41IHN0YXJzLiANCg0KIyMjIFBsb3QgMzoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGggPSA3LjV9DQojVGhpcyBpcyB0byBjcmVhdGUgYSBicmVhayBzbyB0aGF0IHRoZSByZWZsZWN0aW9uIHNlY3Rpb24gYXBwZWFycyBiZW5lYXRoIHRoZSBwbG90Lg0KYGBgDQoNCiMgUmVmbGVjdGlvbg0KDQpUaGUgWWVscCBhY2FkZW1pYyBkYXRhIHNldCBvbiBidXNpbmVzc2VzIGNvbnRhaW4gaW5mb3JtYXRpb24gb24gb3ZlciAxNTAgdGhvdXNhbmQgZXN0YWJsaXNobWVudHMgYWNyb3NzIDEwMSB2YXJpYWJsZXMgd2l0aGluIE5vcnRoIEFtZXJpY2EgYW5kIGJleW9uZC4gQWx0aG91Z2ggdGhlIGFuYWx5c2lzIHdhcyBkb25lIG9uIHRoZSB3aG9sZSBkYXRhIHNldCBmcm9tIHRpbWUgdG8gdGltZSwgSSB3YXMgbWFpbmx5IGludGVyZXN0ZWQgaW4gb3BlcmF0aW5nIHJlc3RhdXJhbnRzIHdpdGhpbiBOb3J0aCBBbWVyaWNhIHdoaWNoIGJyb3VnaHQgdGhpcyBudW1iZXIgZG93biB0byBhcm91bmQgMjYtMjcgdGhvdXNhbmQgZXN0YWJsaXNobWVudHMuIEJ1dCBldmVuIHNvLCBJIHdhcyBhYmxlIHRvIHBlcmZvcm0gYSB3aWRlIHZhcmlldHkgb2YgYW5hbHlzZXMgaW4gdGVybXMgb2YgZXhwbG9yaW5nIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBwcmljZSwgWWVscCBzdGFycywgcmV2aWV3IGNvdW50IGFtb25nIG1hbnkgb3RoZXIgdmFyaWFibGVzIGFjcm9zcyBhIHdpZGUgcmFuZ2Ugb2YgZ2VvZ3JhcGhpZXMgb24gYSBzdGF0ZSBhbmQgY2l0eSBsZXZlbC4gSW4gdGhpcyBwcm9jZXNzLCBJIGNyZWF0ZWQgbWFueSBwbG90cyBhbmQgbWFwcywgY2FsY3VsYXRlZCBzdW1tYXJ5IHN0YXRpc3RpY3MgYW5kIGVtcGxveWVkIGxpbmVhciBtb2RlbHMgdG8gZXhwbG9yZSB0aGlzIHJpY2ggYW5kIGluZm9ybWF0aXZlIGRhdGEgc2V0Lg0KDQpUaGVyZSB3YXMgYSBjbGVhciB0cmVuZCBiZXR3ZWVuIHByaWNlIHJhbmdlIGFuZCBzdGFycywgd2l0aCByZXN0YXVyYW50cyBpbiBoaWdoZXIgcHJpY2UgcmFuZ2VzIGdlbmVyYWxseSByZWNlaXZpbmcgbXVjaCBoaWdoZXIgWWVscCBzdGFyIHJhdGluZ3MuIFRoYXQgYmVpbmcgc2FpZCwgaGF2aW5nIGEgaGlnaGVyIFllbHAgc3RhciByYXRpbmcgZGlkIG5vdCBuZWNlc3Nhcmx5IHRyYW5zbGF0ZSBpbnRvIHZhbHVlLCBhcyB3ZSBzYXcgdGhhdCBjaXRpZXMgc3VjaCBhcyBNb250cmVhbCB3aGljaCBzY29yZWQgaGlnaGx5IG9uIGJvdGggaW5kaWNhdG9ycyBlbmRlZCBwZXJmb3JtaW5nIHRoZSB3b3JzdCBjb21wYXJlZCB0byBvdGhlciBjaXRpZXMgd2hlbiBpdCBjYW1lIHRvIHRoZSB2YWx1ZSBwZXIgZG9sbGFyIHNwZW50LiBPbmUgb3RoZXIgaW1wb3J0YW50IHBvaW50IGlzIHRoYXQgcmVzdGF1cmFudHMgaW4gbW9yZSBleHBlbnNpdmUgcHJpY2UgcmFuZ2VzIHRlbmQgdG8gYmUgbG9jYXRlZCBpbiBkb3dudG93biBhcmVhcywgdGhvdWdoIGluIHRoZSBjYXNlIG9mIHRoZSBQaG9lbml4IG1ldHJvcG9saXRhbiBhcmVhLCB0aGVzZSB3ZXJlIGZvdW5kIG1haW5seSBpbiBTY290dHNkYWxlIChhIHN1YnVyYiB0byB0aGUgZWFzdCkuIA0KDQpBbm90aGVyIGludGVyZXN0aW5nIGluc2lnaHQgaXMgdGhhdCBhY3Jvc3MgYWxsIHByaWNlIHJhbmdlcywgbm9pc2llciByZXN0YXVyYW50cyB0ZW5kZWQgdG8gYmUgcmF0ZWQgbW9yZSBwb29ybHkgdGhhbiB0aG9zZSB0aGF0IHdlcmUgcXVpZXRlci4gUmVzdGF1cmFudHMgb2YgYWxsIG5vaXNlIGxldmVscyB3ZXJlIGRpc3RyaWJ1dGVkIHRocm91Z2hvdXQgdGhlIGNpdGllcyBhbmFseXplZCwgYW5kIHRoZXJlIHdhcyBnZW5lcmFsbHkgbm90IG9uZSBhcmVhIHdoZXJlIHlvdSBjb3VsZCBmaW5kIHJlc3RhdXJhbnRzIG9mIGEgc3BlY2lmaWMgbm9pc2UgbGV2ZWwuDQoNCkFsdGhvdWdoIEkgZXhwZWN0ZWQgbWFueSBlc3RhYmxpc2htZW50cyB0byBoYXZlIGxvdyByZXZpZXcgY291bnRzLCBJIHdhcyBxdWl0ZSBzdXJwcmlzZWQgdG8gZmluZCB0aGF0IHRoZSBtZWRpYW4gbnVtYmVyIG9mIHJldmlld3MgcGVyIGVzdGFibGlzaG1lbnQgd2FzIHNvIGxvdywgYW5kIHRoYXQgdGhlIGRpc3BlcnNpb24gb2YgcmV2aWV3IGNvdW50cyBhY3Jvc3MgZGlmZmVyZW50IGVzdGFibGlzaG1lbnRzIHdhcyBzbyBsYXJnZS4gU29tZXRoaW5nIHRoYXQgZGlkIG5vdCBzdXJwcmlzZSBtZSwgaG93ZXZlciwgd2FzIHRoYXQgYWxtb3N0IGFsbCBjbG9zZWQgZXN0YWJsaXNobWVudHMgdGVuZGVkIHRvIGhhdmUgYSBsb3dlciByZXZpZXcgY291bnQuIEZpbmFsbHksIG9uZSBsYXN0IHRoaW5nIHRoYXQgSSBmb3VuZCBpbnRlcmVzdGluZyB3YXMgdGhhdCByZXN0YXVyYW50cyB0aGF0IHNlcnZlZCBvbmx5IGJlZXIgYW5kIHdpbmUgdGVuZGVkIHRvIGJlIHJhdGVkIGhpZ2hlciB0aGFuIHRob3NlIHRoYXQgaGFkIGZ1bGwgYmFyIHNlcnZpY2UuDQoNCk9uZSBvZiB0aGUgYmlnZ2VzdCBsaW1pdGF0aW9ucyBvZiB0aGUgZGF0YSBzZXQgd2FzIHRoZSBsYWNrIG9mIGRhdGEgZnJvbSBvdGhlciBOb3J0aCBBbWVyaWNhbiBjaXRpZXMvc3RhdGVzLiBJdCBpcyBub3Qga25vd24gd2h5IG9yIGhvdyB0aGVzZSBjaXRpZXMgd2VyZSBjaG9zZW4sIGFuZCBpdCBpcyBub3QgY2xlYXIgaWYgZXZlcnkgZXN0YWJsaXNobWVudCBpbiB0aGVzZSBjaXRpZXMgaXMgY292ZXJlZCBpbiB0aGUgZGF0YSBzZXQuIFRoZSB2YXJpYWJsZXMgcHJlc2VudCBpbiB0aGlzIGRhdGEgc2V0IGFsc28gc2tld2VkIGhlYXZpbHkgdG93YXJkcyB0aGUgYW5hbHlzaXMgb2YgcmVzdGF1cmFudHMsIHNvIHRoYXQgb3RoZXIgWWVscC1yYXRlZCBlc3RhYmxpc2htZW50cyBzdWNoIGFzIHNwYXMsIHNhbG9ucyBhbmQgaG90ZWxzIHdlcmUgaGFyZGVyIHRvIGFuYWx5emUuIEl0IHdvdWxkIGJlIGludGVyZXN0aW5nIHRvIGhhdmUgYSBtdWNoIGxhcmdlciBzZWxlY3Rpb24gb2YgY2l0aWVzL3N0YXRlcyB0byBjaG9vc2UgZnJvbSwgYW5kIHRvIGJlIGFibGUgdG8gdGVzdCB0aGUgbGluZWFyIG1vZGVscyBhYm92ZSB0byBzZWUgaWYgdGhlIHJlbGF0aW9uc2hpcHMgZW5kIHVwIGJlY29taW5nIHN0cm9uZ2VyIG9yIHdlYWtlciB3aXRoIGEgcmljaGVyIGRhdGEgc2V0Lg0KDQo=